init commit
This commit is contained in:
143
output/Libraries/AForge.Imaging/AForge/Imaging/Blob.cs
Normal file
143
output/Libraries/AForge.Imaging/AForge/Imaging/Blob.cs
Normal file
@@ -0,0 +1,143 @@
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
|
||||
namespace AForge.Imaging;
|
||||
|
||||
public class Blob
|
||||
{
|
||||
private UnmanagedImage image;
|
||||
|
||||
private bool originalSize;
|
||||
|
||||
private Rectangle rect;
|
||||
|
||||
private int id;
|
||||
|
||||
private int area;
|
||||
|
||||
private Point cog;
|
||||
|
||||
private double fullness;
|
||||
|
||||
private Color colorMean = Color.Black;
|
||||
|
||||
private Color colorStdDev = Color.Black;
|
||||
|
||||
[Browsable(false)]
|
||||
public UnmanagedImage Image
|
||||
{
|
||||
get
|
||||
{
|
||||
return image;
|
||||
}
|
||||
internal set
|
||||
{
|
||||
image = value;
|
||||
}
|
||||
}
|
||||
|
||||
[Browsable(false)]
|
||||
public bool OriginalSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return originalSize;
|
||||
}
|
||||
internal set
|
||||
{
|
||||
originalSize = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Rectangle Rectangle => rect;
|
||||
|
||||
[Browsable(false)]
|
||||
public int ID
|
||||
{
|
||||
get
|
||||
{
|
||||
return id;
|
||||
}
|
||||
internal set
|
||||
{
|
||||
id = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int Area
|
||||
{
|
||||
get
|
||||
{
|
||||
return area;
|
||||
}
|
||||
internal set
|
||||
{
|
||||
area = value;
|
||||
}
|
||||
}
|
||||
|
||||
public double Fullness
|
||||
{
|
||||
get
|
||||
{
|
||||
return fullness;
|
||||
}
|
||||
internal set
|
||||
{
|
||||
fullness = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Point CenterOfGravity
|
||||
{
|
||||
get
|
||||
{
|
||||
return cog;
|
||||
}
|
||||
internal set
|
||||
{
|
||||
cog = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Color ColorMean
|
||||
{
|
||||
get
|
||||
{
|
||||
return colorMean;
|
||||
}
|
||||
internal set
|
||||
{
|
||||
colorMean = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Color ColorStdDev
|
||||
{
|
||||
get
|
||||
{
|
||||
return colorStdDev;
|
||||
}
|
||||
internal set
|
||||
{
|
||||
colorStdDev = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Blob(int id, Rectangle rect)
|
||||
{
|
||||
this.id = id;
|
||||
this.rect = rect;
|
||||
}
|
||||
|
||||
public Blob(Blob source)
|
||||
{
|
||||
id = source.id;
|
||||
rect = source.rect;
|
||||
cog = source.cog;
|
||||
area = source.area;
|
||||
fullness = source.fullness;
|
||||
colorMean = source.colorMean;
|
||||
colorStdDev = source.colorStdDev;
|
||||
}
|
||||
}
|
||||
379
output/Libraries/AForge.Imaging/AForge/Imaging/BlobCounter.cs
Normal file
379
output/Libraries/AForge.Imaging/AForge/Imaging/BlobCounter.cs
Normal file
@@ -0,0 +1,379 @@
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging;
|
||||
|
||||
public class BlobCounter : BlobCounterBase
|
||||
{
|
||||
private byte backgroundThresholdR;
|
||||
|
||||
private byte backgroundThresholdG;
|
||||
|
||||
private byte backgroundThresholdB;
|
||||
|
||||
public Color BackgroundThreshold
|
||||
{
|
||||
get
|
||||
{
|
||||
return Color.FromArgb(backgroundThresholdR, backgroundThresholdG, backgroundThresholdB);
|
||||
}
|
||||
set
|
||||
{
|
||||
backgroundThresholdR = value.R;
|
||||
backgroundThresholdG = value.G;
|
||||
backgroundThresholdB = value.B;
|
||||
}
|
||||
}
|
||||
|
||||
public BlobCounter()
|
||||
{
|
||||
}
|
||||
|
||||
public BlobCounter(Bitmap image)
|
||||
: base(image)
|
||||
{
|
||||
}
|
||||
|
||||
public BlobCounter(BitmapData imageData)
|
||||
: base(imageData)
|
||||
{
|
||||
}
|
||||
|
||||
public BlobCounter(UnmanagedImage image)
|
||||
: base(image)
|
||||
{
|
||||
}
|
||||
|
||||
protected unsafe override void BuildObjectsMap(UnmanagedImage image)
|
||||
{
|
||||
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0012: Invalid comparison between Unknown and I4
|
||||
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001f: Invalid comparison between Unknown and I4
|
||||
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002c: Invalid comparison between Unknown and I4
|
||||
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0039: Invalid comparison between Unknown and I4
|
||||
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00e0: Invalid comparison between Unknown and I4
|
||||
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0046: Invalid comparison between Unknown and I4
|
||||
//IL_046c: Unknown result type (might be due to invalid IL or missing references)
|
||||
int stride = image.Stride;
|
||||
if ((int)image.PixelFormat != 198659 && (int)image.PixelFormat != 137224 && (int)image.PixelFormat != 139273 && (int)image.PixelFormat != 2498570 && (int)image.PixelFormat != 925707)
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Unsupported pixel format of the source image.");
|
||||
}
|
||||
if (imageWidth == 1)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("BlobCounter cannot process images that are one pixel wide. Rotate the image or use RecursiveBlobCounter.");
|
||||
}
|
||||
int num = imageWidth - 1;
|
||||
objectLabels = new int[imageWidth * imageHeight];
|
||||
int num2 = 0;
|
||||
int num3 = (imageWidth / 2 + 1) * (imageHeight / 2 + 1) + 1;
|
||||
int[] array = new int[num3];
|
||||
for (int i = 0; i < num3; i++)
|
||||
{
|
||||
array[i] = i;
|
||||
}
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
int num4 = 0;
|
||||
if ((int)image.PixelFormat == 198659)
|
||||
{
|
||||
int num5 = stride - imageWidth;
|
||||
if (*ptr > backgroundThresholdG)
|
||||
{
|
||||
num2 = (objectLabels[num4] = num2 + 1);
|
||||
}
|
||||
ptr++;
|
||||
num4++;
|
||||
int num6 = 1;
|
||||
while (num6 < imageWidth)
|
||||
{
|
||||
if (*ptr > backgroundThresholdG)
|
||||
{
|
||||
if (ptr[-1] > backgroundThresholdG)
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
num2 = (objectLabels[num4] = num2 + 1);
|
||||
}
|
||||
}
|
||||
num6++;
|
||||
ptr++;
|
||||
num4++;
|
||||
}
|
||||
ptr += num5;
|
||||
for (int j = 1; j < imageHeight; j++)
|
||||
{
|
||||
if (*ptr > backgroundThresholdG)
|
||||
{
|
||||
if (ptr[-stride] > backgroundThresholdG)
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 - imageWidth];
|
||||
}
|
||||
else if (ptr[1 - stride] <= backgroundThresholdG)
|
||||
{
|
||||
num2 = (objectLabels[num4] = num2 + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 + 1 - imageWidth];
|
||||
}
|
||||
}
|
||||
ptr++;
|
||||
num4++;
|
||||
int num7 = 1;
|
||||
while (num7 < num)
|
||||
{
|
||||
if (*ptr > backgroundThresholdG)
|
||||
{
|
||||
if (ptr[-1] > backgroundThresholdG)
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 - 1];
|
||||
}
|
||||
else if (ptr[-1 - stride] > backgroundThresholdG)
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 - 1 - imageWidth];
|
||||
}
|
||||
else if (ptr[-stride] > backgroundThresholdG)
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 - imageWidth];
|
||||
}
|
||||
if (ptr[1 - stride] > backgroundThresholdG)
|
||||
{
|
||||
if (objectLabels[num4] == 0)
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 + 1 - imageWidth];
|
||||
}
|
||||
else
|
||||
{
|
||||
int num8 = objectLabels[num4];
|
||||
int num9 = objectLabels[num4 + 1 - imageWidth];
|
||||
if (num8 != num9 && array[num8] != array[num9])
|
||||
{
|
||||
if (array[num8] == num8)
|
||||
{
|
||||
array[num8] = array[num9];
|
||||
}
|
||||
else if (array[num9] == num9)
|
||||
{
|
||||
array[num9] = array[num8];
|
||||
}
|
||||
else
|
||||
{
|
||||
array[array[num8]] = array[num9];
|
||||
array[num8] = array[num9];
|
||||
}
|
||||
for (int k = 1; k <= num2; k++)
|
||||
{
|
||||
if (array[k] != k)
|
||||
{
|
||||
int num10;
|
||||
for (num10 = array[k]; num10 != array[num10]; num10 = array[num10])
|
||||
{
|
||||
}
|
||||
array[k] = num10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (objectLabels[num4] == 0)
|
||||
{
|
||||
num2 = (objectLabels[num4] = num2 + 1);
|
||||
}
|
||||
}
|
||||
num7++;
|
||||
ptr++;
|
||||
num4++;
|
||||
}
|
||||
if (*ptr > backgroundThresholdG)
|
||||
{
|
||||
if (ptr[-1] > backgroundThresholdG)
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 - 1];
|
||||
}
|
||||
else if (ptr[-1 - stride] > backgroundThresholdG)
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 - 1 - imageWidth];
|
||||
}
|
||||
else if (ptr[-stride] > backgroundThresholdG)
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 - imageWidth];
|
||||
}
|
||||
else
|
||||
{
|
||||
num2 = (objectLabels[num4] = num2 + 1);
|
||||
}
|
||||
}
|
||||
ptr++;
|
||||
num4++;
|
||||
ptr += num5;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int num11 = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
int num12 = stride - imageWidth * num11;
|
||||
int num13 = stride - num11;
|
||||
int num14 = stride + num11;
|
||||
if ((ptr[2] | ptr[1] | *ptr) != 0)
|
||||
{
|
||||
num2 = (objectLabels[num4] = num2 + 1);
|
||||
}
|
||||
ptr += num11;
|
||||
num4++;
|
||||
int num15 = 1;
|
||||
while (num15 < imageWidth)
|
||||
{
|
||||
if (ptr[2] > backgroundThresholdR || ptr[1] > backgroundThresholdG || *ptr > backgroundThresholdB)
|
||||
{
|
||||
if (ptr[2 - num11] > backgroundThresholdR || ptr[1 - num11] > backgroundThresholdG || ptr[-num11] > backgroundThresholdB)
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
num2 = (objectLabels[num4] = num2 + 1);
|
||||
}
|
||||
}
|
||||
num15++;
|
||||
ptr += num11;
|
||||
num4++;
|
||||
}
|
||||
ptr += num12;
|
||||
for (int l = 1; l < imageHeight; l++)
|
||||
{
|
||||
if (ptr[2] > backgroundThresholdR || ptr[1] > backgroundThresholdG || *ptr > backgroundThresholdB)
|
||||
{
|
||||
if (ptr[2 - stride] > backgroundThresholdR || ptr[1 - stride] > backgroundThresholdG || ptr[-stride] > backgroundThresholdB)
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 - imageWidth];
|
||||
}
|
||||
else if (ptr[2 - num13] <= backgroundThresholdR && ptr[1 - num13] <= backgroundThresholdG && ptr[-num13] <= backgroundThresholdB)
|
||||
{
|
||||
num2 = (objectLabels[num4] = num2 + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 + 1 - imageWidth];
|
||||
}
|
||||
}
|
||||
ptr += num11;
|
||||
num4++;
|
||||
int num16 = 1;
|
||||
while (num16 < imageWidth - 1)
|
||||
{
|
||||
if (ptr[2] > backgroundThresholdR || ptr[1] > backgroundThresholdG || *ptr > backgroundThresholdB)
|
||||
{
|
||||
if (ptr[2 - num11] > backgroundThresholdR || ptr[1 - num11] > backgroundThresholdG || ptr[-num11] > backgroundThresholdB)
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 - 1];
|
||||
}
|
||||
else if (ptr[2 - num14] > backgroundThresholdR || ptr[1 - num14] > backgroundThresholdG || ptr[-num14] > backgroundThresholdB)
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 - 1 - imageWidth];
|
||||
}
|
||||
else if (ptr[2 - stride] > backgroundThresholdR || ptr[1 - stride] > backgroundThresholdG || ptr[-stride] > backgroundThresholdB)
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 - imageWidth];
|
||||
}
|
||||
if (ptr[2 - num13] > backgroundThresholdR || ptr[1 - num13] > backgroundThresholdG || ptr[-num13] > backgroundThresholdB)
|
||||
{
|
||||
if (objectLabels[num4] == 0)
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 + 1 - imageWidth];
|
||||
}
|
||||
else
|
||||
{
|
||||
int num17 = objectLabels[num4];
|
||||
int num18 = objectLabels[num4 + 1 - imageWidth];
|
||||
if (num17 != num18 && array[num17] != array[num18])
|
||||
{
|
||||
if (array[num17] == num17)
|
||||
{
|
||||
array[num17] = array[num18];
|
||||
}
|
||||
else if (array[num18] == num18)
|
||||
{
|
||||
array[num18] = array[num17];
|
||||
}
|
||||
else
|
||||
{
|
||||
array[array[num17]] = array[num18];
|
||||
array[num17] = array[num18];
|
||||
}
|
||||
for (int m = 1; m <= num2; m++)
|
||||
{
|
||||
if (array[m] != m)
|
||||
{
|
||||
int num19;
|
||||
for (num19 = array[m]; num19 != array[num19]; num19 = array[num19])
|
||||
{
|
||||
}
|
||||
array[m] = num19;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (objectLabels[num4] == 0)
|
||||
{
|
||||
num2 = (objectLabels[num4] = num2 + 1);
|
||||
}
|
||||
}
|
||||
num16++;
|
||||
ptr += num11;
|
||||
num4++;
|
||||
}
|
||||
if (ptr[2] > backgroundThresholdR || ptr[1] > backgroundThresholdG || *ptr > backgroundThresholdB)
|
||||
{
|
||||
if (ptr[2 - num11] > backgroundThresholdR || ptr[1 - num11] > backgroundThresholdG || ptr[-num11] > backgroundThresholdB)
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 - 1];
|
||||
}
|
||||
else if (ptr[2 - num14] > backgroundThresholdR || ptr[1 - num14] > backgroundThresholdG || ptr[-num14] > backgroundThresholdB)
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 - 1 - imageWidth];
|
||||
}
|
||||
else if (ptr[2 - stride] > backgroundThresholdR || ptr[1 - stride] > backgroundThresholdG || ptr[-stride] > backgroundThresholdB)
|
||||
{
|
||||
objectLabels[num4] = objectLabels[num4 - imageWidth];
|
||||
}
|
||||
else
|
||||
{
|
||||
num2 = (objectLabels[num4] = num2 + 1);
|
||||
}
|
||||
}
|
||||
ptr += num11;
|
||||
num4++;
|
||||
ptr += num12;
|
||||
}
|
||||
}
|
||||
int[] array2 = new int[array.Length];
|
||||
objectsCount = 0;
|
||||
for (int n = 1; n <= num2; n++)
|
||||
{
|
||||
if (array[n] == n)
|
||||
{
|
||||
array2[n] = ++objectsCount;
|
||||
}
|
||||
}
|
||||
for (int num20 = 1; num20 <= num2; num20++)
|
||||
{
|
||||
if (array[num20] != num20)
|
||||
{
|
||||
array2[num20] = array2[array[num20]];
|
||||
}
|
||||
}
|
||||
int num21 = 0;
|
||||
for (int num22 = objectLabels.Length; num21 < num22; num21++)
|
||||
{
|
||||
objectLabels[num21] = array2[objectLabels[num21]];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,798 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging;
|
||||
|
||||
public abstract class BlobCounterBase
|
||||
{
|
||||
private class BlobsSorter : IComparer<Blob>
|
||||
{
|
||||
private ObjectsOrder order;
|
||||
|
||||
public BlobsSorter(ObjectsOrder order)
|
||||
{
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
public int Compare(Blob a, Blob b)
|
||||
{
|
||||
Rectangle rectangle = a.Rectangle;
|
||||
Rectangle rectangle2 = b.Rectangle;
|
||||
return order switch
|
||||
{
|
||||
ObjectsOrder.Size => rectangle2.Width * rectangle2.Height - rectangle.Width * rectangle.Height,
|
||||
ObjectsOrder.Area => b.Area - a.Area,
|
||||
ObjectsOrder.YX => rectangle.Y * 100000 + rectangle.X - (rectangle2.Y * 100000 + rectangle2.X),
|
||||
ObjectsOrder.XY => rectangle.X * 100000 + rectangle.Y - (rectangle2.X * 100000 + rectangle2.Y),
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private List<Blob> blobs = new List<Blob>();
|
||||
|
||||
private ObjectsOrder objectsOrder;
|
||||
|
||||
private bool filterBlobs;
|
||||
|
||||
private IBlobsFilter filter;
|
||||
|
||||
private bool coupledSizeFiltering;
|
||||
|
||||
private int minWidth = 1;
|
||||
|
||||
private int minHeight = 1;
|
||||
|
||||
private int maxWidth = int.MaxValue;
|
||||
|
||||
private int maxHeight = int.MaxValue;
|
||||
|
||||
protected int objectsCount;
|
||||
|
||||
protected int[] objectLabels;
|
||||
|
||||
protected int imageWidth;
|
||||
|
||||
protected int imageHeight;
|
||||
|
||||
public int ObjectsCount => objectsCount;
|
||||
|
||||
public int[] ObjectLabels => objectLabels;
|
||||
|
||||
public ObjectsOrder ObjectsOrder
|
||||
{
|
||||
get
|
||||
{
|
||||
return objectsOrder;
|
||||
}
|
||||
set
|
||||
{
|
||||
objectsOrder = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool FilterBlobs
|
||||
{
|
||||
get
|
||||
{
|
||||
return filterBlobs;
|
||||
}
|
||||
set
|
||||
{
|
||||
filterBlobs = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CoupledSizeFiltering
|
||||
{
|
||||
get
|
||||
{
|
||||
return coupledSizeFiltering;
|
||||
}
|
||||
set
|
||||
{
|
||||
coupledSizeFiltering = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int MinWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return minWidth;
|
||||
}
|
||||
set
|
||||
{
|
||||
minWidth = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int MinHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
return minHeight;
|
||||
}
|
||||
set
|
||||
{
|
||||
minHeight = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int MaxWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return maxWidth;
|
||||
}
|
||||
set
|
||||
{
|
||||
maxWidth = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int MaxHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
return maxHeight;
|
||||
}
|
||||
set
|
||||
{
|
||||
maxHeight = value;
|
||||
}
|
||||
}
|
||||
|
||||
public IBlobsFilter BlobsFilter
|
||||
{
|
||||
get
|
||||
{
|
||||
return filter;
|
||||
}
|
||||
set
|
||||
{
|
||||
filter = value;
|
||||
}
|
||||
}
|
||||
|
||||
public BlobCounterBase()
|
||||
{
|
||||
}
|
||||
|
||||
public BlobCounterBase(Bitmap image)
|
||||
{
|
||||
ProcessImage(image);
|
||||
}
|
||||
|
||||
public BlobCounterBase(BitmapData imageData)
|
||||
{
|
||||
ProcessImage(imageData);
|
||||
}
|
||||
|
||||
public BlobCounterBase(UnmanagedImage image)
|
||||
{
|
||||
ProcessImage(image);
|
||||
}
|
||||
|
||||
public void ProcessImage(Bitmap image)
|
||||
{
|
||||
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)1, ((Image)image).PixelFormat);
|
||||
try
|
||||
{
|
||||
ProcessImage(val);
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
}
|
||||
}
|
||||
|
||||
public void ProcessImage(BitmapData imageData)
|
||||
{
|
||||
ProcessImage(new UnmanagedImage(imageData));
|
||||
}
|
||||
|
||||
public void ProcessImage(UnmanagedImage image)
|
||||
{
|
||||
imageWidth = image.Width;
|
||||
imageHeight = image.Height;
|
||||
BuildObjectsMap(image);
|
||||
CollectObjectsInfo(image);
|
||||
if (filterBlobs)
|
||||
{
|
||||
int[] array = new int[objectsCount + 1];
|
||||
for (int i = 1; i <= objectsCount; i++)
|
||||
{
|
||||
array[i] = i;
|
||||
}
|
||||
int num = 0;
|
||||
if (filter == null)
|
||||
{
|
||||
for (int num2 = objectsCount - 1; num2 >= 0; num2--)
|
||||
{
|
||||
int width = blobs[num2].Rectangle.Width;
|
||||
int height = blobs[num2].Rectangle.Height;
|
||||
if (!coupledSizeFiltering)
|
||||
{
|
||||
if (width < minWidth || height < minHeight || width > maxWidth || height > maxHeight)
|
||||
{
|
||||
array[num2 + 1] = 0;
|
||||
num++;
|
||||
blobs.RemoveAt(num2);
|
||||
}
|
||||
}
|
||||
else if ((width < minWidth && height < minHeight) || (width > maxWidth && height > maxHeight))
|
||||
{
|
||||
array[num2 + 1] = 0;
|
||||
num++;
|
||||
blobs.RemoveAt(num2);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int num3 = objectsCount - 1; num3 >= 0; num3--)
|
||||
{
|
||||
if (!filter.Check(blobs[num3]))
|
||||
{
|
||||
array[num3 + 1] = 0;
|
||||
num++;
|
||||
blobs.RemoveAt(num3);
|
||||
}
|
||||
}
|
||||
}
|
||||
int num4 = 0;
|
||||
for (int j = 1; j <= objectsCount; j++)
|
||||
{
|
||||
if (array[j] != 0)
|
||||
{
|
||||
num4 = (array[j] = num4 + 1);
|
||||
}
|
||||
}
|
||||
int k = 0;
|
||||
for (int num5 = objectLabels.Length; k < num5; k++)
|
||||
{
|
||||
objectLabels[k] = array[objectLabels[k]];
|
||||
}
|
||||
objectsCount -= num;
|
||||
int l = 0;
|
||||
for (int count = blobs.Count; l < count; l++)
|
||||
{
|
||||
blobs[l].ID = l + 1;
|
||||
}
|
||||
}
|
||||
if (objectsOrder != ObjectsOrder.None)
|
||||
{
|
||||
blobs.Sort(new BlobsSorter(objectsOrder));
|
||||
}
|
||||
}
|
||||
|
||||
public Rectangle[] GetObjectsRectangles()
|
||||
{
|
||||
if (objectLabels == null)
|
||||
{
|
||||
throw new ApplicationException("Image should be processed before to collect objects map.");
|
||||
}
|
||||
Rectangle[] array = new Rectangle[objectsCount];
|
||||
for (int i = 0; i < objectsCount; i++)
|
||||
{
|
||||
ref Rectangle reference = ref array[i];
|
||||
reference = blobs[i].Rectangle;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public Blob[] GetObjectsInformation()
|
||||
{
|
||||
if (objectLabels == null)
|
||||
{
|
||||
throw new ApplicationException("Image should be processed before to collect objects map.");
|
||||
}
|
||||
Blob[] array = new Blob[objectsCount];
|
||||
for (int i = 0; i < objectsCount; i++)
|
||||
{
|
||||
array[i] = new Blob(blobs[i]);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public Blob[] GetObjects(Bitmap image, bool extractInOriginalSize)
|
||||
{
|
||||
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
|
||||
Blob[] array = null;
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)1, ((Image)image).PixelFormat);
|
||||
try
|
||||
{
|
||||
return GetObjects(new UnmanagedImage(val), extractInOriginalSize);
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe Blob[] GetObjects(UnmanagedImage image, bool extractInOriginalSize)
|
||||
{
|
||||
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001e: Invalid comparison between Unknown and I4
|
||||
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002b: Invalid comparison between Unknown and I4
|
||||
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0038: Invalid comparison between Unknown and I4
|
||||
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0045: Invalid comparison between Unknown and I4
|
||||
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0052: Invalid comparison between Unknown and I4
|
||||
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_005f: Invalid comparison between Unknown and I4
|
||||
//IL_0157: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (objectLabels == null)
|
||||
{
|
||||
throw new ApplicationException("Image should be processed before to collect objects map.");
|
||||
}
|
||||
if ((int)image.PixelFormat != 137224 && (int)image.PixelFormat != 198659 && (int)image.PixelFormat != 139273 && (int)image.PixelFormat != 2498570 && (int)image.PixelFormat != 139273 && (int)image.PixelFormat != 925707)
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Unsupported pixel format of the provided image.");
|
||||
}
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
int stride = image.Stride;
|
||||
int num = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
Blob[] array = new Blob[objectsCount];
|
||||
for (int i = 0; i < objectsCount; i++)
|
||||
{
|
||||
int width2 = blobs[i].Rectangle.Width;
|
||||
int height2 = blobs[i].Rectangle.Height;
|
||||
int width3 = (extractInOriginalSize ? width : width2);
|
||||
int height3 = (extractInOriginalSize ? height : height2);
|
||||
int x = blobs[i].Rectangle.X;
|
||||
int num2 = x + width2 - 1;
|
||||
int y = blobs[i].Rectangle.Y;
|
||||
int num3 = y + height2 - 1;
|
||||
int iD = blobs[i].ID;
|
||||
UnmanagedImage unmanagedImage = UnmanagedImage.Create(width3, height3, image.PixelFormat);
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer() + (nint)y * (nint)stride + (nint)x * (nint)num;
|
||||
byte* ptr2 = (byte*)unmanagedImage.ImageData.ToPointer();
|
||||
int num4 = y * width + x;
|
||||
if (extractInOriginalSize)
|
||||
{
|
||||
ptr2 += y * unmanagedImage.Stride + x * num;
|
||||
}
|
||||
int num5 = stride - width2 * num;
|
||||
int num6 = unmanagedImage.Stride - width2 * num;
|
||||
int num7 = width - width2;
|
||||
for (int j = y; j <= num3; j++)
|
||||
{
|
||||
int num8 = x;
|
||||
while (num8 <= num2)
|
||||
{
|
||||
if (objectLabels[num4] == iD)
|
||||
{
|
||||
*ptr2 = *ptr;
|
||||
if (num > 1)
|
||||
{
|
||||
ptr2[1] = ptr[1];
|
||||
ptr2[2] = ptr[2];
|
||||
if (num > 3)
|
||||
{
|
||||
ptr2[3] = ptr[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
num8++;
|
||||
num4++;
|
||||
ptr2 += num;
|
||||
ptr += num;
|
||||
}
|
||||
ptr += num5;
|
||||
ptr2 += num6;
|
||||
num4 += num7;
|
||||
}
|
||||
array[i] = new Blob(blobs[i]);
|
||||
array[i].Image = unmanagedImage;
|
||||
array[i].OriginalSize = extractInOriginalSize;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public void ExtractBlobsImage(Bitmap image, Blob blob, bool extractInOriginalSize)
|
||||
{
|
||||
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)1, ((Image)image).PixelFormat);
|
||||
try
|
||||
{
|
||||
ExtractBlobsImage(new UnmanagedImage(val), blob, extractInOriginalSize);
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe void ExtractBlobsImage(UnmanagedImage image, Blob blob, bool extractInOriginalSize)
|
||||
{
|
||||
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001e: Invalid comparison between Unknown and I4
|
||||
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002b: Invalid comparison between Unknown and I4
|
||||
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0038: Invalid comparison between Unknown and I4
|
||||
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0045: Invalid comparison between Unknown and I4
|
||||
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0052: Invalid comparison between Unknown and I4
|
||||
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_005f: Invalid comparison between Unknown and I4
|
||||
if (objectLabels == null)
|
||||
{
|
||||
throw new ApplicationException("Image should be processed before to collect objects map.");
|
||||
}
|
||||
if ((int)image.PixelFormat != 137224 && (int)image.PixelFormat != 198659 && (int)image.PixelFormat != 139273 && (int)image.PixelFormat != 2498570 && (int)image.PixelFormat != 139273 && (int)image.PixelFormat != 925707)
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Unsupported pixel format of the provided image.");
|
||||
}
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
int stride = image.Stride;
|
||||
int num = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
int width2 = blob.Rectangle.Width;
|
||||
int height2 = blob.Rectangle.Height;
|
||||
int width3 = (extractInOriginalSize ? width : width2);
|
||||
int height3 = (extractInOriginalSize ? height : height2);
|
||||
int left = blob.Rectangle.Left;
|
||||
int num2 = left + width2 - 1;
|
||||
int top = blob.Rectangle.Top;
|
||||
int num3 = top + height2 - 1;
|
||||
int iD = blob.ID;
|
||||
blob.Image = UnmanagedImage.Create(width3, height3, image.PixelFormat);
|
||||
blob.OriginalSize = extractInOriginalSize;
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer() + (nint)top * (nint)stride + (nint)left * (nint)num;
|
||||
byte* ptr2 = (byte*)blob.Image.ImageData.ToPointer();
|
||||
int num4 = top * width + left;
|
||||
if (extractInOriginalSize)
|
||||
{
|
||||
ptr2 += top * blob.Image.Stride + left * num;
|
||||
}
|
||||
int num5 = stride - width2 * num;
|
||||
int num6 = blob.Image.Stride - width2 * num;
|
||||
int num7 = width - width2;
|
||||
for (int i = top; i <= num3; i++)
|
||||
{
|
||||
int num8 = left;
|
||||
while (num8 <= num2)
|
||||
{
|
||||
if (objectLabels[num4] == iD)
|
||||
{
|
||||
*ptr2 = *ptr;
|
||||
if (num > 1)
|
||||
{
|
||||
ptr2[1] = ptr[1];
|
||||
ptr2[2] = ptr[2];
|
||||
if (num > 3)
|
||||
{
|
||||
ptr2[3] = ptr[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
num8++;
|
||||
num4++;
|
||||
ptr2 += num;
|
||||
ptr += num;
|
||||
}
|
||||
ptr += num5;
|
||||
ptr2 += num6;
|
||||
num4 += num7;
|
||||
}
|
||||
}
|
||||
|
||||
public void GetBlobsLeftAndRightEdges(Blob blob, out List<IntPoint> leftEdge, out List<IntPoint> rightEdge)
|
||||
{
|
||||
if (objectLabels == null)
|
||||
{
|
||||
throw new ApplicationException("Image should be processed before to collect objects map.");
|
||||
}
|
||||
leftEdge = new List<IntPoint>();
|
||||
rightEdge = new List<IntPoint>();
|
||||
int left = blob.Rectangle.Left;
|
||||
int num = left + blob.Rectangle.Width - 1;
|
||||
int top = blob.Rectangle.Top;
|
||||
int num2 = top + blob.Rectangle.Height - 1;
|
||||
int iD = blob.ID;
|
||||
for (int i = top; i <= num2; i++)
|
||||
{
|
||||
int num3 = i * imageWidth + left;
|
||||
int num4 = left;
|
||||
while (num4 <= num)
|
||||
{
|
||||
if (objectLabels[num3] == iD)
|
||||
{
|
||||
leftEdge.Add(new IntPoint(num4, i));
|
||||
break;
|
||||
}
|
||||
num4++;
|
||||
num3++;
|
||||
}
|
||||
num3 = i * imageWidth + num;
|
||||
int num5 = num;
|
||||
while (num5 >= left)
|
||||
{
|
||||
if (objectLabels[num3] == iD)
|
||||
{
|
||||
rightEdge.Add(new IntPoint(num5, i));
|
||||
break;
|
||||
}
|
||||
num5--;
|
||||
num3--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void GetBlobsTopAndBottomEdges(Blob blob, out List<IntPoint> topEdge, out List<IntPoint> bottomEdge)
|
||||
{
|
||||
if (objectLabels == null)
|
||||
{
|
||||
throw new ApplicationException("Image should be processed before to collect objects map.");
|
||||
}
|
||||
topEdge = new List<IntPoint>();
|
||||
bottomEdge = new List<IntPoint>();
|
||||
int left = blob.Rectangle.Left;
|
||||
int num = left + blob.Rectangle.Width - 1;
|
||||
int top = blob.Rectangle.Top;
|
||||
int num2 = top + blob.Rectangle.Height - 1;
|
||||
int iD = blob.ID;
|
||||
for (int i = left; i <= num; i++)
|
||||
{
|
||||
int num3 = top * imageWidth + i;
|
||||
int num4 = top;
|
||||
while (num4 <= num2)
|
||||
{
|
||||
if (objectLabels[num3] == iD)
|
||||
{
|
||||
topEdge.Add(new IntPoint(i, num4));
|
||||
break;
|
||||
}
|
||||
num4++;
|
||||
num3 += imageWidth;
|
||||
}
|
||||
num3 = num2 * imageWidth + i;
|
||||
int num5 = num2;
|
||||
while (num5 >= top)
|
||||
{
|
||||
if (objectLabels[num3] == iD)
|
||||
{
|
||||
bottomEdge.Add(new IntPoint(i, num5));
|
||||
break;
|
||||
}
|
||||
num5--;
|
||||
num3 -= imageWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<IntPoint> GetBlobsEdgePoints(Blob blob)
|
||||
{
|
||||
if (objectLabels == null)
|
||||
{
|
||||
throw new ApplicationException("Image should be processed before to collect objects map.");
|
||||
}
|
||||
List<IntPoint> list = new List<IntPoint>();
|
||||
int left = blob.Rectangle.Left;
|
||||
int num = left + blob.Rectangle.Width - 1;
|
||||
int top = blob.Rectangle.Top;
|
||||
int num2 = top + blob.Rectangle.Height - 1;
|
||||
int iD = blob.ID;
|
||||
int[] array = new int[blob.Rectangle.Height];
|
||||
int[] array2 = new int[blob.Rectangle.Height];
|
||||
for (int i = top; i <= num2; i++)
|
||||
{
|
||||
int num3 = i * imageWidth + left;
|
||||
int num4 = left;
|
||||
while (num4 <= num)
|
||||
{
|
||||
if (objectLabels[num3] == iD)
|
||||
{
|
||||
list.Add(new IntPoint(num4, i));
|
||||
array[i - top] = num4;
|
||||
break;
|
||||
}
|
||||
num4++;
|
||||
num3++;
|
||||
}
|
||||
num3 = i * imageWidth + num;
|
||||
int num5 = num;
|
||||
while (num5 >= left)
|
||||
{
|
||||
if (objectLabels[num3] == iD)
|
||||
{
|
||||
if (array[i - top] != num5)
|
||||
{
|
||||
list.Add(new IntPoint(num5, i));
|
||||
}
|
||||
array2[i - top] = num5;
|
||||
break;
|
||||
}
|
||||
num5--;
|
||||
num3--;
|
||||
}
|
||||
}
|
||||
for (int j = left; j <= num; j++)
|
||||
{
|
||||
int num6 = top * imageWidth + j;
|
||||
int num7 = top;
|
||||
int num8 = 0;
|
||||
while (num7 <= num2)
|
||||
{
|
||||
if (objectLabels[num6] == iD)
|
||||
{
|
||||
if (array[num8] != j && array2[num8] != j)
|
||||
{
|
||||
list.Add(new IntPoint(j, num7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
num7++;
|
||||
num8++;
|
||||
num6 += imageWidth;
|
||||
}
|
||||
num6 = num2 * imageWidth + j;
|
||||
int num9 = num2;
|
||||
int num10 = num2 - top;
|
||||
while (num9 >= top)
|
||||
{
|
||||
if (objectLabels[num6] == iD)
|
||||
{
|
||||
if (array[num10] != j && array2[num10] != j)
|
||||
{
|
||||
list.Add(new IntPoint(j, num9));
|
||||
}
|
||||
break;
|
||||
}
|
||||
num9--;
|
||||
num10--;
|
||||
num6 -= imageWidth;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
protected abstract void BuildObjectsMap(UnmanagedImage image);
|
||||
|
||||
private unsafe void CollectObjectsInfo(UnmanagedImage image)
|
||||
{
|
||||
//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0108: Invalid comparison between Unknown and I4
|
||||
//IL_0263: Unknown result type (might be due to invalid IL or missing references)
|
||||
int num = 0;
|
||||
int[] array = new int[objectsCount + 1];
|
||||
int[] array2 = new int[objectsCount + 1];
|
||||
int[] array3 = new int[objectsCount + 1];
|
||||
int[] array4 = new int[objectsCount + 1];
|
||||
int[] array5 = new int[objectsCount + 1];
|
||||
long[] array6 = new long[objectsCount + 1];
|
||||
long[] array7 = new long[objectsCount + 1];
|
||||
long[] array8 = new long[objectsCount + 1];
|
||||
long[] array9 = new long[objectsCount + 1];
|
||||
long[] array10 = new long[objectsCount + 1];
|
||||
long[] array11 = new long[objectsCount + 1];
|
||||
long[] array12 = new long[objectsCount + 1];
|
||||
long[] array13 = new long[objectsCount + 1];
|
||||
for (int i = 1; i <= objectsCount; i++)
|
||||
{
|
||||
array[i] = imageWidth;
|
||||
array2[i] = imageHeight;
|
||||
}
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
if ((int)image.PixelFormat == 198659)
|
||||
{
|
||||
int num2 = image.Stride - imageWidth;
|
||||
for (int j = 0; j < imageHeight; j++)
|
||||
{
|
||||
int num3 = 0;
|
||||
while (num3 < imageWidth)
|
||||
{
|
||||
int num4 = objectLabels[num];
|
||||
if (num4 != 0)
|
||||
{
|
||||
if (num3 < array[num4])
|
||||
{
|
||||
array[num4] = num3;
|
||||
}
|
||||
if (num3 > array3[num4])
|
||||
{
|
||||
array3[num4] = num3;
|
||||
}
|
||||
if (j < array2[num4])
|
||||
{
|
||||
array2[num4] = j;
|
||||
}
|
||||
if (j > array4[num4])
|
||||
{
|
||||
array4[num4] = j;
|
||||
}
|
||||
array5[num4]++;
|
||||
array6[num4] += num3;
|
||||
array7[num4] += j;
|
||||
byte b = *ptr;
|
||||
array9[num4] += b;
|
||||
array12[num4] += b * b;
|
||||
}
|
||||
num3++;
|
||||
num++;
|
||||
ptr++;
|
||||
}
|
||||
ptr += num2;
|
||||
}
|
||||
for (int k = 1; k <= objectsCount; k++)
|
||||
{
|
||||
array8[k] = (array10[k] = array9[k]);
|
||||
array11[k] = (array13[k] = array12[k]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int num5 = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
int num6 = image.Stride - imageWidth * num5;
|
||||
for (int l = 0; l < imageHeight; l++)
|
||||
{
|
||||
int num7 = 0;
|
||||
while (num7 < imageWidth)
|
||||
{
|
||||
int num4 = objectLabels[num];
|
||||
if (num4 != 0)
|
||||
{
|
||||
if (num7 < array[num4])
|
||||
{
|
||||
array[num4] = num7;
|
||||
}
|
||||
if (num7 > array3[num4])
|
||||
{
|
||||
array3[num4] = num7;
|
||||
}
|
||||
if (l < array2[num4])
|
||||
{
|
||||
array2[num4] = l;
|
||||
}
|
||||
if (l > array4[num4])
|
||||
{
|
||||
array4[num4] = l;
|
||||
}
|
||||
array5[num4]++;
|
||||
array6[num4] += num7;
|
||||
array7[num4] += l;
|
||||
byte b2 = ptr[2];
|
||||
byte b3 = ptr[1];
|
||||
byte b4 = *ptr;
|
||||
array8[num4] += b2;
|
||||
array9[num4] += b3;
|
||||
array10[num4] += b4;
|
||||
array11[num4] += b2 * b2;
|
||||
array12[num4] += b3 * b3;
|
||||
array13[num4] += b4 * b4;
|
||||
}
|
||||
num7++;
|
||||
num++;
|
||||
ptr += num5;
|
||||
}
|
||||
ptr += num6;
|
||||
}
|
||||
}
|
||||
blobs.Clear();
|
||||
for (int m = 1; m <= objectsCount; m++)
|
||||
{
|
||||
int num8 = array5[m];
|
||||
Blob blob = new Blob(m, new Rectangle(array[m], array2[m], array3[m] - array[m] + 1, array4[m] - array2[m] + 1));
|
||||
blob.Area = num8;
|
||||
blob.Fullness = (double)num8 / (double)((array3[m] - array[m] + 1) * (array4[m] - array2[m] + 1));
|
||||
blob.CenterOfGravity = new Point((float)array6[m] / (float)num8, (float)array7[m] / (float)num8);
|
||||
blob.ColorMean = Color.FromArgb((byte)(array8[m] / num8), (byte)(array9[m] / num8), (byte)(array10[m] / num8));
|
||||
blob.ColorStdDev = Color.FromArgb((byte)System.Math.Sqrt(array11[m] / num8 - blob.ColorMean.R * blob.ColorMean.R), (byte)System.Math.Sqrt(array12[m] / num8 - blob.ColorMean.G * blob.ColorMean.G), (byte)System.Math.Sqrt(array13[m] / num8 - blob.ColorMean.B * blob.ColorMean.B));
|
||||
blobs.Add(blob);
|
||||
}
|
||||
}
|
||||
}
|
||||
23
output/Libraries/AForge.Imaging/AForge/Imaging/BlockMatch.cs
Normal file
23
output/Libraries/AForge.Imaging/AForge/Imaging/BlockMatch.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
namespace AForge.Imaging;
|
||||
|
||||
public class BlockMatch
|
||||
{
|
||||
private IntPoint sourcePoint;
|
||||
|
||||
private IntPoint matchPoint;
|
||||
|
||||
private float similarity;
|
||||
|
||||
public IntPoint SourcePoint => sourcePoint;
|
||||
|
||||
public IntPoint MatchPoint => matchPoint;
|
||||
|
||||
public float Similarity => similarity;
|
||||
|
||||
public BlockMatch(IntPoint sourcePoint, IntPoint matchPoint, float similarity)
|
||||
{
|
||||
this.sourcePoint = sourcePoint;
|
||||
this.matchPoint = matchPoint;
|
||||
this.similarity = similarity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace AForge.Imaging.ColorReduction;
|
||||
|
||||
public sealed class BurkesColorDithering : ColorErrorDiffusionToAdjacentNeighbors
|
||||
{
|
||||
public BurkesColorDithering()
|
||||
: base(new int[2][]
|
||||
{
|
||||
new int[2] { 8, 4 },
|
||||
new int[5] { 2, 4, 8, 4, 2 }
|
||||
})
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
namespace AForge.Imaging.ColorReduction;
|
||||
|
||||
public class ColorErrorDiffusionToAdjacentNeighbors : ErrorDiffusionColorDithering
|
||||
{
|
||||
private int[][] coefficients;
|
||||
|
||||
private int coefficientsSum;
|
||||
|
||||
public int[][] Coefficients
|
||||
{
|
||||
get
|
||||
{
|
||||
return coefficients;
|
||||
}
|
||||
set
|
||||
{
|
||||
coefficients = value;
|
||||
CalculateCoefficientsSum();
|
||||
}
|
||||
}
|
||||
|
||||
public ColorErrorDiffusionToAdjacentNeighbors(int[][] coefficients)
|
||||
{
|
||||
this.coefficients = coefficients;
|
||||
CalculateCoefficientsSum();
|
||||
}
|
||||
|
||||
protected unsafe override void Diffuse(int rError, int gError, int bError, byte* ptr)
|
||||
{
|
||||
int[] array = coefficients[0];
|
||||
int num = 1;
|
||||
int num2 = pixelSize;
|
||||
int num3 = 0;
|
||||
int num4 = array.Length;
|
||||
while (num3 < num4 && x + num < width)
|
||||
{
|
||||
int num5 = ptr[num2 + 2] + rError * array[num3] / coefficientsSum;
|
||||
num5 = ((num5 >= 0) ? ((num5 > 255) ? 255 : num5) : 0);
|
||||
ptr[num2 + 2] = (byte)num5;
|
||||
int num6 = ptr[num2 + 1] + gError * array[num3] / coefficientsSum;
|
||||
num6 = ((num6 >= 0) ? ((num6 > 255) ? 255 : num6) : 0);
|
||||
ptr[num2 + 1] = (byte)num6;
|
||||
int num7 = ptr[num2] + bError * array[num3] / coefficientsSum;
|
||||
num7 = ((num7 >= 0) ? ((num7 > 255) ? 255 : num7) : 0);
|
||||
ptr[num2] = (byte)num7;
|
||||
num++;
|
||||
num3++;
|
||||
num2 += pixelSize;
|
||||
}
|
||||
int i = 1;
|
||||
for (int num8 = coefficients.Length; i < num8 && y + i < height; i++)
|
||||
{
|
||||
ptr += stride;
|
||||
array = coefficients[i];
|
||||
int num9 = 0;
|
||||
int num10 = array.Length;
|
||||
int num11 = -(num10 >> 1);
|
||||
int num12 = -(num10 >> 1) * pixelSize;
|
||||
while (num9 < num10 && x + num11 < width)
|
||||
{
|
||||
if (x + num11 >= 0)
|
||||
{
|
||||
int num5 = ptr[num12 + 2] + rError * array[num9] / coefficientsSum;
|
||||
num5 = ((num5 >= 0) ? ((num5 > 255) ? 255 : num5) : 0);
|
||||
ptr[num12 + 2] = (byte)num5;
|
||||
int num6 = ptr[num12 + 1] + gError * array[num9] / coefficientsSum;
|
||||
num6 = ((num6 >= 0) ? ((num6 > 255) ? 255 : num6) : 0);
|
||||
ptr[num12 + 1] = (byte)num6;
|
||||
int num7 = ptr[num12] + bError * array[num9] / coefficientsSum;
|
||||
num7 = ((num7 >= 0) ? ((num7 > 255) ? 255 : num7) : 0);
|
||||
ptr[num12] = (byte)num7;
|
||||
}
|
||||
num11++;
|
||||
num9++;
|
||||
num12 += pixelSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateCoefficientsSum()
|
||||
{
|
||||
coefficientsSum = 0;
|
||||
int i = 0;
|
||||
for (int num = coefficients.Length; i < num; i++)
|
||||
{
|
||||
int[] array = coefficients[i];
|
||||
int j = 0;
|
||||
for (int num2 = array.Length; j < num2; j++)
|
||||
{
|
||||
coefficientsSum += array[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.ColorReduction;
|
||||
|
||||
public class ColorImageQuantizer
|
||||
{
|
||||
private IColorQuantizer quantizer;
|
||||
|
||||
private bool useCaching;
|
||||
|
||||
[NonSerialized]
|
||||
private Color[] paletteToUse;
|
||||
|
||||
[NonSerialized]
|
||||
private Dictionary<Color, int> cache = new Dictionary<Color, int>();
|
||||
|
||||
public IColorQuantizer Quantizer
|
||||
{
|
||||
get
|
||||
{
|
||||
return quantizer;
|
||||
}
|
||||
set
|
||||
{
|
||||
quantizer = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool UseCaching
|
||||
{
|
||||
get
|
||||
{
|
||||
return useCaching;
|
||||
}
|
||||
set
|
||||
{
|
||||
useCaching = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ColorImageQuantizer(IColorQuantizer quantizer)
|
||||
{
|
||||
this.quantizer = quantizer;
|
||||
}
|
||||
|
||||
public Color[] CalculatePalette(Bitmap image, int paletteSize)
|
||||
{
|
||||
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)1, ((Image)image).PixelFormat);
|
||||
try
|
||||
{
|
||||
return CalculatePalette(new UnmanagedImage(val), paletteSize);
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe Color[] CalculatePalette(UnmanagedImage image, int paletteSize)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0018: Invalid comparison between Unknown and I4
|
||||
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0025: Invalid comparison between Unknown and I4
|
||||
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0032: Invalid comparison between Unknown and I4
|
||||
if ((int)image.PixelFormat != 137224 && (int)image.PixelFormat != 139273 && (int)image.PixelFormat != 2498570 && (int)image.PixelFormat != 925707)
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Unsupported format of the source image.");
|
||||
}
|
||||
quantizer.Clear();
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
int num = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
int num2 = image.Stride - width * num;
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
int num3 = 0;
|
||||
while (num3 < width)
|
||||
{
|
||||
quantizer.AddColor(Color.FromArgb(ptr[2], ptr[1], *ptr));
|
||||
num3++;
|
||||
ptr += num;
|
||||
}
|
||||
ptr += num2;
|
||||
}
|
||||
return quantizer.GetPalette(paletteSize);
|
||||
}
|
||||
|
||||
public Bitmap ReduceColors(Bitmap image, int paletteSize)
|
||||
{
|
||||
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)1, ((Image)image).PixelFormat);
|
||||
try
|
||||
{
|
||||
Bitmap val2 = ReduceColors(new UnmanagedImage(val), paletteSize);
|
||||
if (((Image)image).HorizontalResolution > 0f && ((Image)image).VerticalResolution > 0f)
|
||||
{
|
||||
val2.SetResolution(((Image)image).HorizontalResolution, ((Image)image).VerticalResolution);
|
||||
}
|
||||
return val2;
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
}
|
||||
}
|
||||
|
||||
public Bitmap ReduceColors(UnmanagedImage image, int paletteSize)
|
||||
{
|
||||
if (paletteSize < 2 || paletteSize > 256)
|
||||
{
|
||||
throw new ArgumentException("Invalid size of the target color palette.");
|
||||
}
|
||||
return ReduceColors(image, CalculatePalette(image, paletteSize));
|
||||
}
|
||||
|
||||
public Bitmap ReduceColors(Bitmap image, Color[] palette)
|
||||
{
|
||||
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)1, ((Image)image).PixelFormat);
|
||||
try
|
||||
{
|
||||
Bitmap val2 = ReduceColors(new UnmanagedImage(val), palette);
|
||||
if (((Image)image).HorizontalResolution > 0f && ((Image)image).VerticalResolution > 0f)
|
||||
{
|
||||
val2.SetResolution(((Image)image).HorizontalResolution, ((Image)image).VerticalResolution);
|
||||
}
|
||||
return val2;
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe Bitmap ReduceColors(UnmanagedImage image, Color[] palette)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0018: Invalid comparison between Unknown and I4
|
||||
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0025: Invalid comparison between Unknown and I4
|
||||
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0032: Invalid comparison between Unknown and I4
|
||||
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00b2: Expected O, but got Unknown
|
||||
//IL_0108: Unknown result type (might be due to invalid IL or missing references)
|
||||
if ((int)image.PixelFormat != 137224 && (int)image.PixelFormat != 139273 && (int)image.PixelFormat != 2498570 && (int)image.PixelFormat != 925707)
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Unsupported format of the source image.");
|
||||
}
|
||||
if (palette.Length < 2 || palette.Length > 256)
|
||||
{
|
||||
throw new ArgumentException("Invalid size of the target color palette.");
|
||||
}
|
||||
paletteToUse = palette;
|
||||
cache.Clear();
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
int stride = image.Stride;
|
||||
int num = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
int num2 = stride - width * num;
|
||||
Bitmap val = new Bitmap(width, height, (PixelFormat)((palette.Length > 16) ? 198659 : 197634));
|
||||
ColorPalette palette2 = ((Image)val).Palette;
|
||||
int i = 0;
|
||||
for (int num3 = palette.Length; i < num3; i++)
|
||||
{
|
||||
ref Color reference = ref palette2.Entries[i];
|
||||
reference = palette[i];
|
||||
}
|
||||
((Image)val).Palette = palette2;
|
||||
BitmapData val2 = val.LockBits(new Rectangle(0, 0, width, height), (ImageLockMode)3, ((Image)val).PixelFormat);
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)val2.Scan0.ToPointer();
|
||||
bool flag = palette.Length > 16;
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
byte* ptr3 = ptr2 + (nint)j * (nint)val2.Stride;
|
||||
int num4 = 0;
|
||||
while (num4 < width)
|
||||
{
|
||||
byte b = (byte)GetClosestColor(ptr[2], ptr[1], *ptr);
|
||||
if (flag)
|
||||
{
|
||||
*ptr3 = b;
|
||||
ptr3++;
|
||||
}
|
||||
else if (num4 % 2 == 0)
|
||||
{
|
||||
byte* intPtr = ptr3;
|
||||
*intPtr |= (byte)(b << 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte* intPtr2 = ptr3;
|
||||
*intPtr2 |= b;
|
||||
ptr3++;
|
||||
}
|
||||
num4++;
|
||||
ptr += num;
|
||||
}
|
||||
ptr += num2;
|
||||
}
|
||||
val.UnlockBits(val2);
|
||||
return val;
|
||||
}
|
||||
|
||||
private int GetClosestColor(int red, int green, int blue)
|
||||
{
|
||||
Color key = Color.FromArgb(red, green, blue);
|
||||
if (useCaching && cache.ContainsKey(key))
|
||||
{
|
||||
return cache[key];
|
||||
}
|
||||
int num = 0;
|
||||
int num2 = int.MaxValue;
|
||||
int i = 0;
|
||||
for (int num3 = paletteToUse.Length; i < num3; i++)
|
||||
{
|
||||
int num4 = red - paletteToUse[i].R;
|
||||
int num5 = green - paletteToUse[i].G;
|
||||
int num6 = blue - paletteToUse[i].B;
|
||||
int num7 = num4 * num4 + num5 * num5 + num6 * num6;
|
||||
if (num7 < num2)
|
||||
{
|
||||
num2 = num7;
|
||||
num = (byte)i;
|
||||
}
|
||||
}
|
||||
if (useCaching)
|
||||
{
|
||||
cache.Add(key, num);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.ColorReduction;
|
||||
|
||||
public abstract class ErrorDiffusionColorDithering
|
||||
{
|
||||
private bool useCaching;
|
||||
|
||||
protected int x;
|
||||
|
||||
protected int y;
|
||||
|
||||
protected int width;
|
||||
|
||||
protected int height;
|
||||
|
||||
protected int stride;
|
||||
|
||||
protected int pixelSize;
|
||||
|
||||
private Color[] colorTable = new Color[16]
|
||||
{
|
||||
Color.Black,
|
||||
Color.DarkBlue,
|
||||
Color.DarkGreen,
|
||||
Color.DarkCyan,
|
||||
Color.DarkRed,
|
||||
Color.DarkMagenta,
|
||||
Color.DarkKhaki,
|
||||
Color.LightGray,
|
||||
Color.Gray,
|
||||
Color.Blue,
|
||||
Color.Green,
|
||||
Color.Cyan,
|
||||
Color.Red,
|
||||
Color.Magenta,
|
||||
Color.Yellow,
|
||||
Color.White
|
||||
};
|
||||
|
||||
[NonSerialized]
|
||||
private Dictionary<Color, byte> cache = new Dictionary<Color, byte>();
|
||||
|
||||
public Color[] ColorTable
|
||||
{
|
||||
get
|
||||
{
|
||||
return colorTable;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (colorTable.Length < 2 || colorTable.Length > 256)
|
||||
{
|
||||
throw new ArgumentException("Color table length must be in the [2, 256] range.");
|
||||
}
|
||||
colorTable = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool UseCaching
|
||||
{
|
||||
get
|
||||
{
|
||||
return useCaching;
|
||||
}
|
||||
set
|
||||
{
|
||||
useCaching = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected unsafe abstract void Diffuse(int rError, int gError, int bError, byte* ptr);
|
||||
|
||||
public Bitmap Apply(Bitmap sourceImage)
|
||||
{
|
||||
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||||
BitmapData val = sourceImage.LockBits(new Rectangle(0, 0, ((Image)sourceImage).Width, ((Image)sourceImage).Height), (ImageLockMode)1, ((Image)sourceImage).PixelFormat);
|
||||
Bitmap val2 = null;
|
||||
try
|
||||
{
|
||||
val2 = Apply(new UnmanagedImage(val));
|
||||
if (((Image)sourceImage).HorizontalResolution > 0f && ((Image)sourceImage).VerticalResolution > 0f)
|
||||
{
|
||||
val2.SetResolution(((Image)sourceImage).HorizontalResolution, ((Image)sourceImage).VerticalResolution);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
sourceImage.UnlockBits(val);
|
||||
}
|
||||
return val2;
|
||||
}
|
||||
|
||||
public unsafe Bitmap Apply(UnmanagedImage sourceImage)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0018: Invalid comparison between Unknown and I4
|
||||
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0025: Invalid comparison between Unknown and I4
|
||||
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00c7: Expected O, but got Unknown
|
||||
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0032: Invalid comparison between Unknown and I4
|
||||
//IL_012a: Unknown result type (might be due to invalid IL or missing references)
|
||||
if ((int)sourceImage.PixelFormat != 137224 && (int)sourceImage.PixelFormat != 139273 && (int)sourceImage.PixelFormat != 2498570 && (int)sourceImage.PixelFormat != 925707)
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Unsupported pixel format of the source image.");
|
||||
}
|
||||
cache.Clear();
|
||||
UnmanagedImage unmanagedImage = sourceImage.Clone();
|
||||
width = sourceImage.Width;
|
||||
height = sourceImage.Height;
|
||||
stride = sourceImage.Stride;
|
||||
pixelSize = Image.GetPixelFormatSize(sourceImage.PixelFormat) / 8;
|
||||
int num = stride - width * pixelSize;
|
||||
Bitmap val = new Bitmap(width, height, (PixelFormat)((colorTable.Length > 16) ? 198659 : 197634));
|
||||
ColorPalette palette = ((Image)val).Palette;
|
||||
int i = 0;
|
||||
for (int num2 = colorTable.Length; i < num2; i++)
|
||||
{
|
||||
ref Color reference = ref palette.Entries[i];
|
||||
reference = colorTable[i];
|
||||
}
|
||||
((Image)val).Palette = palette;
|
||||
BitmapData val2 = val.LockBits(new Rectangle(0, 0, width, height), (ImageLockMode)3, ((Image)val).PixelFormat);
|
||||
byte* ptr = (byte*)unmanagedImage.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)val2.Scan0.ToPointer();
|
||||
bool flag = colorTable.Length > 16;
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
byte* ptr3 = ptr2 + (nint)y * (nint)val2.Stride;
|
||||
x = 0;
|
||||
while (x < width)
|
||||
{
|
||||
int num3 = ptr[2];
|
||||
int num4 = ptr[1];
|
||||
int num5 = *ptr;
|
||||
byte colorIndex;
|
||||
Color closestColor = GetClosestColor(num3, num4, num5, out colorIndex);
|
||||
Diffuse(num3 - closestColor.R, num4 - closestColor.G, num5 - closestColor.B, ptr);
|
||||
if (flag)
|
||||
{
|
||||
*ptr3 = colorIndex;
|
||||
ptr3++;
|
||||
}
|
||||
else if (x % 2 == 0)
|
||||
{
|
||||
byte* intPtr = ptr3;
|
||||
*intPtr |= (byte)(colorIndex << 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte* intPtr2 = ptr3;
|
||||
*intPtr2 |= colorIndex;
|
||||
ptr3++;
|
||||
}
|
||||
x++;
|
||||
ptr += pixelSize;
|
||||
}
|
||||
ptr += num;
|
||||
}
|
||||
val.UnlockBits(val2);
|
||||
unmanagedImage.Dispose();
|
||||
return val;
|
||||
}
|
||||
|
||||
private Color GetClosestColor(int red, int green, int blue, out byte colorIndex)
|
||||
{
|
||||
Color key = Color.FromArgb(red, green, blue);
|
||||
if (useCaching && cache.ContainsKey(key))
|
||||
{
|
||||
colorIndex = cache[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
colorIndex = 0;
|
||||
int num = int.MaxValue;
|
||||
int i = 0;
|
||||
for (int num2 = colorTable.Length; i < num2; i++)
|
||||
{
|
||||
int num3 = red - colorTable[i].R;
|
||||
int num4 = green - colorTable[i].G;
|
||||
int num5 = blue - colorTable[i].B;
|
||||
int num6 = num3 * num3 + num4 * num4 + num5 * num5;
|
||||
if (num6 < num)
|
||||
{
|
||||
num = num6;
|
||||
colorIndex = (byte)i;
|
||||
}
|
||||
}
|
||||
if (useCaching)
|
||||
{
|
||||
cache.Add(key, colorIndex);
|
||||
}
|
||||
}
|
||||
return colorTable[colorIndex];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace AForge.Imaging.ColorReduction;
|
||||
|
||||
public sealed class FloydSteinbergColorDithering : ColorErrorDiffusionToAdjacentNeighbors
|
||||
{
|
||||
public FloydSteinbergColorDithering()
|
||||
: base(new int[2][]
|
||||
{
|
||||
new int[1] { 7 },
|
||||
new int[3] { 3, 5, 1 }
|
||||
})
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System.Drawing;
|
||||
|
||||
namespace AForge.Imaging.ColorReduction;
|
||||
|
||||
public interface IColorQuantizer
|
||||
{
|
||||
void AddColor(Color color);
|
||||
|
||||
Color[] GetPalette(int colorCount);
|
||||
|
||||
void Clear();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace AForge.Imaging.ColorReduction;
|
||||
|
||||
public sealed class JarvisJudiceNinkeColorDithering : ColorErrorDiffusionToAdjacentNeighbors
|
||||
{
|
||||
public JarvisJudiceNinkeColorDithering()
|
||||
: base(new int[3][]
|
||||
{
|
||||
new int[2] { 7, 5 },
|
||||
new int[5] { 3, 5, 7, 5, 3 },
|
||||
new int[5] { 1, 3, 5, 3, 1 }
|
||||
})
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
|
||||
namespace AForge.Imaging.ColorReduction;
|
||||
|
||||
internal class MedianCutCube
|
||||
{
|
||||
private class RedComparer : IComparer<Color>
|
||||
{
|
||||
public int Compare(Color c1, Color c2)
|
||||
{
|
||||
return c1.R.CompareTo(c2.R);
|
||||
}
|
||||
}
|
||||
|
||||
private class GreenComparer : IComparer<Color>
|
||||
{
|
||||
public int Compare(Color c1, Color c2)
|
||||
{
|
||||
return c1.G.CompareTo(c2.G);
|
||||
}
|
||||
}
|
||||
|
||||
private class BlueComparer : IComparer<Color>
|
||||
{
|
||||
public int Compare(Color c1, Color c2)
|
||||
{
|
||||
return c1.B.CompareTo(c2.B);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Color> colors;
|
||||
|
||||
private readonly byte minR;
|
||||
|
||||
private readonly byte maxR;
|
||||
|
||||
private readonly byte minG;
|
||||
|
||||
private readonly byte maxG;
|
||||
|
||||
private readonly byte minB;
|
||||
|
||||
private readonly byte maxB;
|
||||
|
||||
private Color? cubeColor = null;
|
||||
|
||||
public int RedSize => maxR - minR;
|
||||
|
||||
public int GreenSize => maxG - minG;
|
||||
|
||||
public int BlueSize => maxB - minB;
|
||||
|
||||
public Color Color
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!cubeColor.HasValue)
|
||||
{
|
||||
int num = 0;
|
||||
int num2 = 0;
|
||||
int num3 = 0;
|
||||
foreach (Color color in colors)
|
||||
{
|
||||
num += color.R;
|
||||
num2 += color.G;
|
||||
num3 += color.B;
|
||||
}
|
||||
int count = colors.Count;
|
||||
if (count != 0)
|
||||
{
|
||||
num /= count;
|
||||
num2 /= count;
|
||||
num3 /= count;
|
||||
}
|
||||
cubeColor = Color.FromArgb(num, num2, num3);
|
||||
}
|
||||
return cubeColor.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public MedianCutCube(List<Color> colors)
|
||||
{
|
||||
this.colors = colors;
|
||||
minR = (minG = (minB = byte.MaxValue));
|
||||
maxR = (maxG = (maxB = 0));
|
||||
foreach (Color color in colors)
|
||||
{
|
||||
if (color.R < minR)
|
||||
{
|
||||
minR = color.R;
|
||||
}
|
||||
if (color.R > maxR)
|
||||
{
|
||||
maxR = color.R;
|
||||
}
|
||||
if (color.G < minG)
|
||||
{
|
||||
minG = color.G;
|
||||
}
|
||||
if (color.G > maxG)
|
||||
{
|
||||
maxG = color.G;
|
||||
}
|
||||
if (color.B < minB)
|
||||
{
|
||||
minB = color.B;
|
||||
}
|
||||
if (color.B > maxB)
|
||||
{
|
||||
maxB = color.B;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SplitAtMedian(int rgbComponent, out MedianCutCube cube1, out MedianCutCube cube2)
|
||||
{
|
||||
switch (rgbComponent)
|
||||
{
|
||||
case 2:
|
||||
colors.Sort(new RedComparer());
|
||||
break;
|
||||
case 1:
|
||||
colors.Sort(new GreenComparer());
|
||||
break;
|
||||
case 0:
|
||||
colors.Sort(new BlueComparer());
|
||||
break;
|
||||
}
|
||||
int num = colors.Count / 2;
|
||||
cube1 = new MedianCutCube(colors.GetRange(0, num));
|
||||
cube2 = new MedianCutCube(colors.GetRange(num, colors.Count - num));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
|
||||
namespace AForge.Imaging.ColorReduction;
|
||||
|
||||
public class MedianCutQuantizer : IColorQuantizer
|
||||
{
|
||||
private List<Color> colors = new List<Color>();
|
||||
|
||||
public void AddColor(Color color)
|
||||
{
|
||||
colors.Add(color);
|
||||
}
|
||||
|
||||
public Color[] GetPalette(int colorCount)
|
||||
{
|
||||
List<MedianCutCube> list = new List<MedianCutCube>();
|
||||
list.Add(new MedianCutCube(colors));
|
||||
SplitCubes(list, colorCount);
|
||||
Color[] array = new Color[colorCount];
|
||||
for (int i = 0; i < colorCount; i++)
|
||||
{
|
||||
ref Color reference = ref array[i];
|
||||
reference = list[i].Color;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
colors.Clear();
|
||||
}
|
||||
|
||||
private void SplitCubes(List<MedianCutCube> cubes, int count)
|
||||
{
|
||||
int num = cubes.Count - 1;
|
||||
while (cubes.Count < count)
|
||||
{
|
||||
MedianCutCube medianCutCube = cubes[num];
|
||||
MedianCutCube cube;
|
||||
MedianCutCube cube2;
|
||||
if (medianCutCube.RedSize >= medianCutCube.GreenSize && medianCutCube.RedSize >= medianCutCube.BlueSize)
|
||||
{
|
||||
medianCutCube.SplitAtMedian(2, out cube, out cube2);
|
||||
}
|
||||
else if (medianCutCube.GreenSize >= medianCutCube.BlueSize)
|
||||
{
|
||||
medianCutCube.SplitAtMedian(1, out cube, out cube2);
|
||||
}
|
||||
else
|
||||
{
|
||||
medianCutCube.SplitAtMedian(0, out cube, out cube2);
|
||||
}
|
||||
cubes.RemoveAt(num);
|
||||
cubes.Insert(num, cube);
|
||||
cubes.Insert(num, cube2);
|
||||
if (--num < 0)
|
||||
{
|
||||
num = cubes.Count - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.ColorReduction;
|
||||
|
||||
public class OrderedColorDithering
|
||||
{
|
||||
private bool useCaching;
|
||||
|
||||
private Color[] colorTable = new Color[16]
|
||||
{
|
||||
Color.Black,
|
||||
Color.DarkBlue,
|
||||
Color.DarkGreen,
|
||||
Color.DarkCyan,
|
||||
Color.DarkRed,
|
||||
Color.DarkMagenta,
|
||||
Color.DarkKhaki,
|
||||
Color.LightGray,
|
||||
Color.Gray,
|
||||
Color.Blue,
|
||||
Color.Green,
|
||||
Color.Cyan,
|
||||
Color.Red,
|
||||
Color.Magenta,
|
||||
Color.Yellow,
|
||||
Color.White
|
||||
};
|
||||
|
||||
private byte[,] matrix = new byte[4, 4]
|
||||
{
|
||||
{ 2, 18, 6, 22 },
|
||||
{ 26, 10, 30, 14 },
|
||||
{ 8, 24, 4, 20 },
|
||||
{ 32, 16, 28, 12 }
|
||||
};
|
||||
|
||||
[NonSerialized]
|
||||
private Dictionary<Color, byte> cache = new Dictionary<Color, byte>();
|
||||
|
||||
public byte[,] ThresholdMatrix
|
||||
{
|
||||
get
|
||||
{
|
||||
return (byte[,])matrix.Clone();
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new NullReferenceException("Threshold matrix cannot be set to null.");
|
||||
}
|
||||
matrix = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Color[] ColorTable
|
||||
{
|
||||
get
|
||||
{
|
||||
return colorTable;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (colorTable.Length < 2 || colorTable.Length > 256)
|
||||
{
|
||||
throw new ArgumentException("Color table length must be in the [2, 256] range.");
|
||||
}
|
||||
colorTable = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool UseCaching
|
||||
{
|
||||
get
|
||||
{
|
||||
return useCaching;
|
||||
}
|
||||
set
|
||||
{
|
||||
useCaching = value;
|
||||
}
|
||||
}
|
||||
|
||||
public OrderedColorDithering()
|
||||
{
|
||||
}
|
||||
|
||||
public OrderedColorDithering(byte[,] matrix)
|
||||
{
|
||||
ThresholdMatrix = matrix;
|
||||
}
|
||||
|
||||
public Bitmap Apply(Bitmap sourceImage)
|
||||
{
|
||||
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||||
BitmapData val = sourceImage.LockBits(new Rectangle(0, 0, ((Image)sourceImage).Width, ((Image)sourceImage).Height), (ImageLockMode)1, ((Image)sourceImage).PixelFormat);
|
||||
Bitmap val2 = null;
|
||||
try
|
||||
{
|
||||
val2 = Apply(new UnmanagedImage(val));
|
||||
if (((Image)sourceImage).HorizontalResolution > 0f && ((Image)sourceImage).VerticalResolution > 0f)
|
||||
{
|
||||
val2.SetResolution(((Image)sourceImage).HorizontalResolution, ((Image)sourceImage).VerticalResolution);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
sourceImage.UnlockBits(val);
|
||||
}
|
||||
return val2;
|
||||
}
|
||||
|
||||
public unsafe Bitmap Apply(UnmanagedImage sourceImage)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0018: Invalid comparison between Unknown and I4
|
||||
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0025: Invalid comparison between Unknown and I4
|
||||
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_008e: Expected O, but got Unknown
|
||||
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0032: Invalid comparison between Unknown and I4
|
||||
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
|
||||
if ((int)sourceImage.PixelFormat != 137224 && (int)sourceImage.PixelFormat != 139273 && (int)sourceImage.PixelFormat != 2498570 && (int)sourceImage.PixelFormat != 925707)
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Unsupported pixel format of the source image.");
|
||||
}
|
||||
cache.Clear();
|
||||
int width = sourceImage.Width;
|
||||
int height = sourceImage.Height;
|
||||
int stride = sourceImage.Stride;
|
||||
int num = Image.GetPixelFormatSize(sourceImage.PixelFormat) / 8;
|
||||
Bitmap val = new Bitmap(width, height, (PixelFormat)((colorTable.Length > 16) ? 198659 : 197634));
|
||||
ColorPalette palette = ((Image)val).Palette;
|
||||
int i = 0;
|
||||
for (int num2 = colorTable.Length; i < num2; i++)
|
||||
{
|
||||
ref Color reference = ref palette.Entries[i];
|
||||
reference = colorTable[i];
|
||||
}
|
||||
((Image)val).Palette = palette;
|
||||
BitmapData val2 = val.LockBits(new Rectangle(0, 0, width, height), (ImageLockMode)3, ((Image)val).PixelFormat);
|
||||
int length = matrix.GetLength(0);
|
||||
int length2 = matrix.GetLength(1);
|
||||
byte* ptr = (byte*)sourceImage.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)val2.Scan0.ToPointer();
|
||||
bool flag = colorTable.Length > 16;
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
byte* ptr3 = ptr2 + (nint)j * (nint)val2.Stride;
|
||||
int num3 = 0;
|
||||
while (num3 < width)
|
||||
{
|
||||
int num4 = matrix[j % length, num3 % length2];
|
||||
int num5 = ptr[2] + num4;
|
||||
int num6 = ptr[1] + num4;
|
||||
int num7 = *ptr + num4;
|
||||
if (num5 > 255)
|
||||
{
|
||||
num5 = 255;
|
||||
}
|
||||
if (num6 > 255)
|
||||
{
|
||||
num6 = 255;
|
||||
}
|
||||
if (num7 > 255)
|
||||
{
|
||||
num7 = 255;
|
||||
}
|
||||
GetClosestColor(num5, num6, num7, out var colorIndex);
|
||||
if (flag)
|
||||
{
|
||||
*ptr3 = colorIndex;
|
||||
ptr3++;
|
||||
}
|
||||
else if (num3 % 2 == 0)
|
||||
{
|
||||
byte* intPtr = ptr3;
|
||||
*intPtr |= (byte)(colorIndex << 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte* intPtr2 = ptr3;
|
||||
*intPtr2 |= colorIndex;
|
||||
ptr3++;
|
||||
}
|
||||
num3++;
|
||||
ptr += num;
|
||||
}
|
||||
}
|
||||
val.UnlockBits(val2);
|
||||
return val;
|
||||
}
|
||||
|
||||
private Color GetClosestColor(int red, int green, int blue, out byte colorIndex)
|
||||
{
|
||||
Color key = Color.FromArgb(red, green, blue);
|
||||
if (useCaching && cache.ContainsKey(key))
|
||||
{
|
||||
colorIndex = cache[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
colorIndex = 0;
|
||||
int num = int.MaxValue;
|
||||
int i = 0;
|
||||
for (int num2 = colorTable.Length; i < num2; i++)
|
||||
{
|
||||
int num3 = red - colorTable[i].R;
|
||||
int num4 = green - colorTable[i].G;
|
||||
int num5 = blue - colorTable[i].B;
|
||||
int num6 = num3 * num3 + num4 * num4 + num5 * num5;
|
||||
if (num6 < num)
|
||||
{
|
||||
num = num6;
|
||||
colorIndex = (byte)i;
|
||||
}
|
||||
}
|
||||
if (useCaching)
|
||||
{
|
||||
cache.Add(key, colorIndex);
|
||||
}
|
||||
}
|
||||
return colorTable[colorIndex];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace AForge.Imaging.ColorReduction;
|
||||
|
||||
public sealed class SierraColorDithering : ColorErrorDiffusionToAdjacentNeighbors
|
||||
{
|
||||
public SierraColorDithering()
|
||||
: base(new int[3][]
|
||||
{
|
||||
new int[2] { 5, 3 },
|
||||
new int[5] { 2, 4, 5, 4, 2 },
|
||||
new int[3] { 2, 3, 2 }
|
||||
})
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace AForge.Imaging.ColorReduction;
|
||||
|
||||
public sealed class StuckiColorDithering : ColorErrorDiffusionToAdjacentNeighbors
|
||||
{
|
||||
public StuckiColorDithering()
|
||||
: base(new int[3][]
|
||||
{
|
||||
new int[2] { 8, 4 },
|
||||
new int[5] { 2, 4, 8, 4, 2 },
|
||||
new int[5] { 1, 2, 4, 2, 1 }
|
||||
})
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using AForge.Math;
|
||||
|
||||
namespace AForge.Imaging.ComplexFilters;
|
||||
|
||||
public class FrequencyFilter : IComplexFilter
|
||||
{
|
||||
private IntRange frequencyRange = new IntRange(0, 1024);
|
||||
|
||||
public IntRange FrequencyRange
|
||||
{
|
||||
get
|
||||
{
|
||||
return frequencyRange;
|
||||
}
|
||||
set
|
||||
{
|
||||
frequencyRange = value;
|
||||
}
|
||||
}
|
||||
|
||||
public FrequencyFilter()
|
||||
{
|
||||
}
|
||||
|
||||
public FrequencyFilter(IntRange frequencyRange)
|
||||
{
|
||||
this.frequencyRange = frequencyRange;
|
||||
}
|
||||
|
||||
public void Apply(ComplexImage complexImage)
|
||||
{
|
||||
if (!complexImage.FourierTransformed)
|
||||
{
|
||||
throw new ArgumentException("The source complex image should be Fourier transformed.");
|
||||
}
|
||||
int width = complexImage.Width;
|
||||
int height = complexImage.Height;
|
||||
int num = width >> 1;
|
||||
int num2 = height >> 1;
|
||||
int min = frequencyRange.Min;
|
||||
int max = frequencyRange.Max;
|
||||
Complex[,] data = complexImage.Data;
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
int num3 = i - num2;
|
||||
for (int j = 0; j < width; j++)
|
||||
{
|
||||
int num4 = j - num;
|
||||
int num5 = (int)System.Math.Sqrt(num4 * num4 + num3 * num3);
|
||||
if (num5 > max || num5 < min)
|
||||
{
|
||||
data[i, j].Re = 0.0;
|
||||
data[i, j].Im = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace AForge.Imaging.ComplexFilters;
|
||||
|
||||
public interface IComplexFilter
|
||||
{
|
||||
void Apply(ComplexImage complexImage);
|
||||
}
|
||||
164
output/Libraries/AForge.Imaging/AForge/Imaging/ComplexImage.cs
Normal file
164
output/Libraries/AForge.Imaging/AForge/Imaging/ComplexImage.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using AForge.Math;
|
||||
|
||||
namespace AForge.Imaging;
|
||||
|
||||
public class ComplexImage : ICloneable
|
||||
{
|
||||
private Complex[,] data;
|
||||
|
||||
private int width;
|
||||
|
||||
private int height;
|
||||
|
||||
private bool fourierTransformed;
|
||||
|
||||
public int Width => width;
|
||||
|
||||
public int Height => height;
|
||||
|
||||
public bool FourierTransformed => fourierTransformed;
|
||||
|
||||
public Complex[,] Data => data;
|
||||
|
||||
protected ComplexImage(int width, int height)
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
data = new Complex[height, width];
|
||||
fourierTransformed = false;
|
||||
}
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
ComplexImage complexImage = new ComplexImage(width, height);
|
||||
Complex[,] array = complexImage.data;
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
for (int j = 0; j < width; j++)
|
||||
{
|
||||
ref Complex reference = ref array[i, j];
|
||||
reference = data[i, j];
|
||||
}
|
||||
}
|
||||
complexImage.fourierTransformed = fourierTransformed;
|
||||
return complexImage;
|
||||
}
|
||||
|
||||
public static ComplexImage FromBitmap(Bitmap image)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
if ((int)((Image)image).PixelFormat != 198659)
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Source image can be graysclae (8bpp indexed) image only.");
|
||||
}
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)1, (PixelFormat)198659);
|
||||
try
|
||||
{
|
||||
return FromBitmap(val);
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe static ComplexImage FromBitmap(BitmapData imageData)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
if ((int)imageData.PixelFormat != 198659)
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Source image can be graysclae (8bpp indexed) image only.");
|
||||
}
|
||||
int num = imageData.Width;
|
||||
int num2 = imageData.Height;
|
||||
int num3 = imageData.Stride - num;
|
||||
if (!Tools.IsPowerOf2(num) || !Tools.IsPowerOf2(num2))
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Image width and height should be power of 2.");
|
||||
}
|
||||
ComplexImage complexImage = new ComplexImage(num, num2);
|
||||
Complex[,] array = complexImage.data;
|
||||
byte* ptr = (byte*)imageData.Scan0.ToPointer();
|
||||
for (int i = 0; i < num2; i++)
|
||||
{
|
||||
int num4 = 0;
|
||||
while (num4 < num)
|
||||
{
|
||||
array[i, num4].Re = (float)(int)(*ptr) / 255f;
|
||||
num4++;
|
||||
ptr++;
|
||||
}
|
||||
ptr += num3;
|
||||
}
|
||||
return complexImage;
|
||||
}
|
||||
|
||||
public unsafe Bitmap ToBitmap()
|
||||
{
|
||||
Bitmap val = Image.CreateGrayscaleImage(width, height);
|
||||
BitmapData val2 = val.LockBits(new Rectangle(0, 0, width, height), (ImageLockMode)3, (PixelFormat)198659);
|
||||
int num = val2.Stride - width;
|
||||
double num2 = (fourierTransformed ? System.Math.Sqrt(width * height) : 1.0);
|
||||
byte* ptr = (byte*)val2.Scan0.ToPointer();
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
int num3 = 0;
|
||||
while (num3 < width)
|
||||
{
|
||||
*ptr = (byte)System.Math.Max(0.0, System.Math.Min(255.0, data[i, num3].Magnitude * num2 * 255.0));
|
||||
num3++;
|
||||
ptr++;
|
||||
}
|
||||
ptr += num;
|
||||
}
|
||||
val.UnlockBits(val2);
|
||||
return val;
|
||||
}
|
||||
|
||||
public void ForwardFourierTransform()
|
||||
{
|
||||
if (fourierTransformed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
for (int j = 0; j < width; j++)
|
||||
{
|
||||
if (((j + i) & 1) != 0)
|
||||
{
|
||||
data[i, j].Re *= -1.0;
|
||||
data[i, j].Im *= -1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
FourierTransform.FFT2(data, FourierTransform.Direction.Forward);
|
||||
fourierTransformed = true;
|
||||
}
|
||||
|
||||
public void BackwardFourierTransform()
|
||||
{
|
||||
if (!fourierTransformed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
FourierTransform.FFT2(data, FourierTransform.Direction.Backward);
|
||||
fourierTransformed = false;
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
for (int j = 0; j < width; j++)
|
||||
{
|
||||
if (((j + i) & 1) != 0)
|
||||
{
|
||||
data[i, j].Re *= -1.0;
|
||||
data[i, j].Im *= -1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging;
|
||||
|
||||
public class DocumentSkewChecker
|
||||
{
|
||||
private int stepsPerDegree;
|
||||
|
||||
private int houghHeight;
|
||||
|
||||
private double thetaStep;
|
||||
|
||||
private double maxSkewToDetect;
|
||||
|
||||
private double[] sinMap;
|
||||
|
||||
private double[] cosMap;
|
||||
|
||||
private bool needToInitialize = true;
|
||||
|
||||
private short[,] houghMap;
|
||||
|
||||
private short maxMapIntensity;
|
||||
|
||||
private int localPeakRadius = 4;
|
||||
|
||||
private ArrayList lines = new ArrayList();
|
||||
|
||||
public int StepsPerDegree
|
||||
{
|
||||
get
|
||||
{
|
||||
return stepsPerDegree;
|
||||
}
|
||||
set
|
||||
{
|
||||
stepsPerDegree = System.Math.Max(1, System.Math.Min(10, value));
|
||||
needToInitialize = true;
|
||||
}
|
||||
}
|
||||
|
||||
public double MaxSkewToDetect
|
||||
{
|
||||
get
|
||||
{
|
||||
return maxSkewToDetect;
|
||||
}
|
||||
set
|
||||
{
|
||||
maxSkewToDetect = System.Math.Max(0.0, System.Math.Min(45.0, value));
|
||||
needToInitialize = true;
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("The property is deprecated and setting it has not any effect. Use MaxSkewToDetect property instead.")]
|
||||
public double MinBeta
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0.0 - maxSkewToDetect;
|
||||
}
|
||||
set
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("The property is deprecated and setting it has not any effect. Use MaxSkewToDetect property instead.")]
|
||||
public double MaxBeta
|
||||
{
|
||||
get
|
||||
{
|
||||
return maxSkewToDetect;
|
||||
}
|
||||
set
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public int LocalPeakRadius
|
||||
{
|
||||
get
|
||||
{
|
||||
return localPeakRadius;
|
||||
}
|
||||
set
|
||||
{
|
||||
localPeakRadius = System.Math.Max(1, System.Math.Min(10, value));
|
||||
}
|
||||
}
|
||||
|
||||
public DocumentSkewChecker()
|
||||
{
|
||||
StepsPerDegree = 10;
|
||||
MaxSkewToDetect = 30.0;
|
||||
}
|
||||
|
||||
public double GetSkewAngle(Bitmap image)
|
||||
{
|
||||
return GetSkewAngle(image, new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height));
|
||||
}
|
||||
|
||||
public double GetSkewAngle(Bitmap image, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
if ((int)((Image)image).PixelFormat != 198659)
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Unsupported pixel format of the source image.");
|
||||
}
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)1, (PixelFormat)198659);
|
||||
try
|
||||
{
|
||||
return GetSkewAngle(new UnmanagedImage(val), rect);
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
}
|
||||
}
|
||||
|
||||
public double GetSkewAngle(BitmapData imageData)
|
||||
{
|
||||
return GetSkewAngle(new UnmanagedImage(imageData), new Rectangle(0, 0, imageData.Width, imageData.Height));
|
||||
}
|
||||
|
||||
public double GetSkewAngle(BitmapData imageData, Rectangle rect)
|
||||
{
|
||||
return GetSkewAngle(new UnmanagedImage(imageData), rect);
|
||||
}
|
||||
|
||||
public double GetSkewAngle(UnmanagedImage image)
|
||||
{
|
||||
return GetSkewAngle(image, new Rectangle(0, 0, image.Width, image.Height));
|
||||
}
|
||||
|
||||
public unsafe double GetSkewAngle(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
if ((int)image.PixelFormat != 198659)
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Unsupported pixel format of the source image.");
|
||||
}
|
||||
InitHoughMap();
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
int num = width / 2;
|
||||
int num2 = height / 2;
|
||||
rect.Intersect(new Rectangle(0, 0, width, height));
|
||||
int num3 = -num + rect.Left;
|
||||
int num4 = -num2 + rect.Top;
|
||||
int num5 = width - num - (width - rect.Right);
|
||||
int num6 = height - num2 - (height - rect.Bottom) - 1;
|
||||
int num7 = image.Stride - rect.Width;
|
||||
int num8 = (int)System.Math.Sqrt(num * num + num2 * num2);
|
||||
int num9 = num8 * 2;
|
||||
houghMap = new short[houghHeight, num9];
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer() + (nint)rect.Top * (nint)image.Stride + rect.Left;
|
||||
byte* ptr2 = ptr + image.Stride;
|
||||
for (int i = num4; i < num6; i++)
|
||||
{
|
||||
int num10 = num3;
|
||||
while (num10 < num5)
|
||||
{
|
||||
if (*ptr < 128 && *ptr2 >= 128)
|
||||
{
|
||||
for (int j = 0; j < houghHeight; j++)
|
||||
{
|
||||
int num11 = (int)(cosMap[j] * (double)num10 - sinMap[j] * (double)i) + num8;
|
||||
if (num11 >= 0 && num11 < num9)
|
||||
{
|
||||
houghMap[j, num11]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
num10++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
ptr += num7;
|
||||
ptr2 += num7;
|
||||
}
|
||||
maxMapIntensity = 0;
|
||||
for (int k = 0; k < houghHeight; k++)
|
||||
{
|
||||
for (int l = 0; l < num9; l++)
|
||||
{
|
||||
if (houghMap[k, l] > maxMapIntensity)
|
||||
{
|
||||
maxMapIntensity = houghMap[k, l];
|
||||
}
|
||||
}
|
||||
}
|
||||
CollectLines((short)(width / 10));
|
||||
HoughLine[] mostIntensiveLines = GetMostIntensiveLines(5);
|
||||
double num12 = 0.0;
|
||||
double num13 = 0.0;
|
||||
HoughLine[] array = mostIntensiveLines;
|
||||
foreach (HoughLine houghLine in array)
|
||||
{
|
||||
if (houghLine.RelativeIntensity > 0.5)
|
||||
{
|
||||
num12 += houghLine.Theta * houghLine.RelativeIntensity;
|
||||
num13 += houghLine.RelativeIntensity;
|
||||
}
|
||||
}
|
||||
if (mostIntensiveLines.Length > 0)
|
||||
{
|
||||
num12 /= num13;
|
||||
}
|
||||
return num12 - 90.0;
|
||||
}
|
||||
|
||||
private HoughLine[] GetMostIntensiveLines(int count)
|
||||
{
|
||||
int num = System.Math.Min(count, lines.Count);
|
||||
HoughLine[] array = new HoughLine[num];
|
||||
lines.CopyTo(0, array, 0, num);
|
||||
return array;
|
||||
}
|
||||
|
||||
private void CollectLines(short minLineIntensity)
|
||||
{
|
||||
int length = houghMap.GetLength(0);
|
||||
int length2 = houghMap.GetLength(1);
|
||||
int num = length2 >> 1;
|
||||
lines.Clear();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
for (int j = 0; j < length2; j++)
|
||||
{
|
||||
short num2 = houghMap[i, j];
|
||||
if (num2 < minLineIntensity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bool flag = false;
|
||||
int k = i - localPeakRadius;
|
||||
for (int num3 = i + localPeakRadius; k < num3; k++)
|
||||
{
|
||||
if (k < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (k >= length || flag)
|
||||
{
|
||||
break;
|
||||
}
|
||||
int l = j - localPeakRadius;
|
||||
for (int num4 = j + localPeakRadius; l < num4; l++)
|
||||
{
|
||||
if (l >= 0)
|
||||
{
|
||||
if (l >= length2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (houghMap[k, l] > num2)
|
||||
{
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!flag)
|
||||
{
|
||||
lines.Add(new HoughLine(90.0 - maxSkewToDetect + (double)i / (double)stepsPerDegree, (short)(j - num), num2, (double)num2 / (double)maxMapIntensity));
|
||||
}
|
||||
}
|
||||
}
|
||||
lines.Sort();
|
||||
}
|
||||
|
||||
private void InitHoughMap()
|
||||
{
|
||||
if (needToInitialize)
|
||||
{
|
||||
needToInitialize = false;
|
||||
houghHeight = (int)(2.0 * maxSkewToDetect * (double)stepsPerDegree);
|
||||
thetaStep = 2.0 * maxSkewToDetect * System.Math.PI / 180.0 / (double)houghHeight;
|
||||
sinMap = new double[houghHeight];
|
||||
cosMap = new double[houghHeight];
|
||||
double num = 90.0 - maxSkewToDetect;
|
||||
for (int i = 0; i < houghHeight; i++)
|
||||
{
|
||||
sinMap[i] = System.Math.Sin(num * System.Math.PI / 180.0 + (double)i * thetaStep);
|
||||
cosMap[i] = System.Math.Cos(num * System.Math.PI / 180.0 + (double)i * thetaStep);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
381
output/Libraries/AForge.Imaging/AForge/Imaging/Drawing.cs
Normal file
381
output/Libraries/AForge.Imaging/AForge/Imaging/Drawing.cs
Normal file
@@ -0,0 +1,381 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging;
|
||||
|
||||
public static class Drawing
|
||||
{
|
||||
public static void FillRectangle(BitmapData imageData, Rectangle rectangle, Color color)
|
||||
{
|
||||
FillRectangle(new UnmanagedImage(imageData), rectangle, color);
|
||||
}
|
||||
|
||||
public unsafe static void FillRectangle(UnmanagedImage image, Rectangle rectangle, Color color)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00cf: Invalid comparison between Unknown and I4
|
||||
//IL_013b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0145: Invalid comparison between Unknown and I4
|
||||
CheckPixelFormat(image.PixelFormat);
|
||||
int num = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
int stride = image.Stride;
|
||||
int x = rectangle.X;
|
||||
int y = rectangle.Y;
|
||||
int num2 = rectangle.X + rectangle.Width - 1;
|
||||
int num3 = rectangle.Y + rectangle.Height - 1;
|
||||
if (x >= width || y >= height || num2 < 0 || num3 < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int num4 = System.Math.Max(0, x);
|
||||
int num5 = System.Math.Min(width - 1, num2);
|
||||
int num6 = System.Math.Max(0, y);
|
||||
int num7 = System.Math.Min(height - 1, num3);
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer() + (nint)num6 * (nint)stride + (nint)num4 * (nint)num;
|
||||
if ((int)image.PixelFormat == 198659)
|
||||
{
|
||||
byte filler = (byte)(0.2125 * (double)(int)color.R + 0.7154 * (double)(int)color.G + 0.0721 * (double)(int)color.B);
|
||||
int count = num5 - num4 + 1;
|
||||
for (int i = num6; i <= num7; i++)
|
||||
{
|
||||
SystemTools.SetUnmanagedMemory(ptr, filler, count);
|
||||
ptr += stride;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ((int)image.PixelFormat == 2498570)
|
||||
{
|
||||
double num8 = (double)(int)color.A / 255.0;
|
||||
double num9 = 1.0 - num8;
|
||||
double num10 = num8 * (double)(int)color.R;
|
||||
double num11 = num8 * (double)(int)color.G;
|
||||
double num12 = num8 * (double)(int)color.B;
|
||||
int num13 = stride - (num5 - num4 + 1) * 4;
|
||||
for (int j = num6; j <= num7; j++)
|
||||
{
|
||||
int num14 = num4;
|
||||
while (num14 <= num5)
|
||||
{
|
||||
double num15 = (double)(int)ptr[3] / 255.0 * num9;
|
||||
ptr[2] = (byte)(num10 + num15 * (double)(int)ptr[2]);
|
||||
ptr[1] = (byte)(num11 + num15 * (double)(int)ptr[1]);
|
||||
*ptr = (byte)(num12 + num15 * (double)(int)(*ptr));
|
||||
ptr[3] = (byte)(255.0 * (num8 + num15));
|
||||
num14++;
|
||||
ptr += 4;
|
||||
}
|
||||
ptr += num13;
|
||||
}
|
||||
return;
|
||||
}
|
||||
byte r = color.R;
|
||||
byte g = color.G;
|
||||
byte b = color.B;
|
||||
int num16 = stride - (num5 - num4 + 1) * num;
|
||||
if (color.A == byte.MaxValue)
|
||||
{
|
||||
for (int k = num6; k <= num7; k++)
|
||||
{
|
||||
int num17 = num4;
|
||||
while (num17 <= num5)
|
||||
{
|
||||
ptr[2] = r;
|
||||
ptr[1] = g;
|
||||
*ptr = b;
|
||||
num17++;
|
||||
ptr += num;
|
||||
}
|
||||
ptr += num16;
|
||||
}
|
||||
return;
|
||||
}
|
||||
int a = color.A;
|
||||
int num18 = 255 - a;
|
||||
int num19 = a * color.R;
|
||||
int num20 = a * color.G;
|
||||
int num21 = a * color.B;
|
||||
for (int l = num6; l <= num7; l++)
|
||||
{
|
||||
int num22 = num4;
|
||||
while (num22 <= num5)
|
||||
{
|
||||
ptr[2] = (byte)((num19 + num18 * ptr[2]) / 255);
|
||||
ptr[1] = (byte)((num20 + num18 * ptr[1]) / 255);
|
||||
*ptr = (byte)((num21 + num18 * *ptr) / 255);
|
||||
num22++;
|
||||
ptr += num;
|
||||
}
|
||||
ptr += num16;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Rectangle(BitmapData imageData, Rectangle rectangle, Color color)
|
||||
{
|
||||
Rectangle(new UnmanagedImage(imageData), rectangle, color);
|
||||
}
|
||||
|
||||
public static void Rectangle(UnmanagedImage image, Rectangle rectangle, Color color)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckPixelFormat(image.PixelFormat);
|
||||
_ = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
_ = image.Stride;
|
||||
int x = rectangle.X;
|
||||
int y = rectangle.Y;
|
||||
int num = rectangle.X + rectangle.Width - 1;
|
||||
int num2 = rectangle.Y + rectangle.Height - 1;
|
||||
if (x < width && y < height && num >= 0 && num2 >= 0)
|
||||
{
|
||||
Line(image, new IntPoint(x, y), new IntPoint(num, y), color);
|
||||
Line(image, new IntPoint(num, num2), new IntPoint(x, num2), color);
|
||||
Line(image, new IntPoint(num, y + 1), new IntPoint(num, num2 - 1), color);
|
||||
Line(image, new IntPoint(x, num2 - 1), new IntPoint(x, y + 1), color);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Line(BitmapData imageData, IntPoint point1, IntPoint point2, Color color)
|
||||
{
|
||||
Line(new UnmanagedImage(imageData), point1, point2, color);
|
||||
}
|
||||
|
||||
public unsafe static void Line(UnmanagedImage image, IntPoint point1, IntPoint point2, Color color)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0116: Invalid comparison between Unknown and I4
|
||||
//IL_045d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0467: Invalid comparison between Unknown and I4
|
||||
//IL_0226: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0230: Invalid comparison between Unknown and I4
|
||||
//IL_04b0: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_04ba: Invalid comparison between Unknown and I4
|
||||
//IL_0279: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0283: Invalid comparison between Unknown and I4
|
||||
CheckPixelFormat(image.PixelFormat);
|
||||
int num = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
int stride = image.Stride;
|
||||
if ((point1.X < 0 && point2.X < 0) || (point1.Y < 0 && point2.Y < 0) || (point1.X >= width && point2.X >= width) || (point1.Y >= height && point2.Y >= height))
|
||||
{
|
||||
return;
|
||||
}
|
||||
CheckEndPoint(width, height, point1, ref point2);
|
||||
CheckEndPoint(width, height, point2, ref point1);
|
||||
if ((point1.X < 0 && point2.X < 0) || (point1.Y < 0 && point2.Y < 0) || (point1.X >= width && point2.X >= width) || (point1.Y >= height && point2.Y >= height))
|
||||
{
|
||||
return;
|
||||
}
|
||||
int x = point1.X;
|
||||
int y = point1.Y;
|
||||
int x2 = point2.X;
|
||||
int y2 = point2.Y;
|
||||
byte b = 0;
|
||||
if ((int)image.PixelFormat == 198659)
|
||||
{
|
||||
b = (byte)(0.2125 * (double)(int)color.R + 0.7154 * (double)(int)color.G + 0.0721 * (double)(int)color.B);
|
||||
}
|
||||
double num2 = (double)(int)color.A / 255.0;
|
||||
double num3 = 1.0 - num2;
|
||||
double num4 = num2 * (double)(int)color.R;
|
||||
double num5 = num2 * (double)(int)color.G;
|
||||
double num6 = num2 * (double)(int)color.B;
|
||||
int num7 = 255 - color.A;
|
||||
int num8 = color.A * color.R;
|
||||
int num9 = color.A * color.G;
|
||||
int num10 = color.A * color.B;
|
||||
int num11 = x2 - x;
|
||||
int num12 = y2 - y;
|
||||
if (System.Math.Abs(num11) >= System.Math.Abs(num12))
|
||||
{
|
||||
float num13 = ((num11 != 0) ? ((float)num12 / (float)num11) : 0f);
|
||||
int num14 = ((num11 > 0) ? 1 : (-1));
|
||||
num11 += num14;
|
||||
if ((int)image.PixelFormat == 198659)
|
||||
{
|
||||
for (int i = 0; i != num11; i += num14)
|
||||
{
|
||||
int num15 = x + i;
|
||||
int num16 = (int)((float)y + num13 * (float)i);
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer() + (nint)num16 * (nint)stride + num15;
|
||||
*ptr = b;
|
||||
}
|
||||
}
|
||||
else if ((int)image.PixelFormat == 2498570)
|
||||
{
|
||||
for (int j = 0; j != num11; j += num14)
|
||||
{
|
||||
int num17 = x + j;
|
||||
int num18 = (int)((float)y + num13 * (float)j);
|
||||
byte* ptr2 = (byte*)image.ImageData.ToPointer() + (nint)num18 * (nint)stride + (nint)num17 * (nint)4;
|
||||
double num19 = (double)(int)ptr2[3] / 255.0 * num3;
|
||||
ptr2[2] = (byte)(num4 + num19 * (double)(int)ptr2[2]);
|
||||
ptr2[1] = (byte)(num5 + num19 * (double)(int)ptr2[1]);
|
||||
*ptr2 = (byte)(num6 + num19 * (double)(int)(*ptr2));
|
||||
ptr2[3] = (byte)(255.0 * (num2 + num19));
|
||||
}
|
||||
}
|
||||
else if (color.A == byte.MaxValue)
|
||||
{
|
||||
for (int k = 0; k != num11; k += num14)
|
||||
{
|
||||
int num20 = x + k;
|
||||
int num21 = (int)((float)y + num13 * (float)k);
|
||||
byte* ptr3 = (byte*)image.ImageData.ToPointer() + (nint)num21 * (nint)stride + (nint)num20 * (nint)num;
|
||||
ptr3[2] = color.R;
|
||||
ptr3[1] = color.G;
|
||||
*ptr3 = color.B;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int l = 0; l != num11; l += num14)
|
||||
{
|
||||
int num22 = x + l;
|
||||
int num23 = (int)((float)y + num13 * (float)l);
|
||||
byte* ptr4 = (byte*)image.ImageData.ToPointer() + (nint)num23 * (nint)stride + (nint)num22 * (nint)num;
|
||||
ptr4[2] = (byte)((num8 + num7 * ptr4[2]) / 255);
|
||||
ptr4[1] = (byte)((num9 + num7 * ptr4[1]) / 255);
|
||||
*ptr4 = (byte)((num10 + num7 * *ptr4) / 255);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
float num24 = ((num12 != 0) ? ((float)num11 / (float)num12) : 0f);
|
||||
int num25 = ((num12 > 0) ? 1 : (-1));
|
||||
num12 += num25;
|
||||
if ((int)image.PixelFormat == 198659)
|
||||
{
|
||||
for (int m = 0; m != num12; m += num25)
|
||||
{
|
||||
int num26 = (int)((float)x + num24 * (float)m);
|
||||
int num27 = y + m;
|
||||
byte* ptr5 = (byte*)image.ImageData.ToPointer() + (nint)num27 * (nint)stride + num26;
|
||||
*ptr5 = b;
|
||||
}
|
||||
}
|
||||
else if ((int)image.PixelFormat == 2498570)
|
||||
{
|
||||
for (int n = 0; n != num12; n += num25)
|
||||
{
|
||||
int num28 = (int)((float)x + num24 * (float)n);
|
||||
int num29 = y + n;
|
||||
byte* ptr6 = (byte*)image.ImageData.ToPointer() + (nint)num29 * (nint)stride + (nint)num28 * (nint)4;
|
||||
double num30 = (double)(int)ptr6[3] / 255.0 * num3;
|
||||
ptr6[2] = (byte)(num4 + num30 * (double)(int)ptr6[2]);
|
||||
ptr6[1] = (byte)(num5 + num30 * (double)(int)ptr6[1]);
|
||||
*ptr6 = (byte)(num6 + num30 * (double)(int)(*ptr6));
|
||||
ptr6[3] = (byte)(255.0 * (num2 + num30));
|
||||
}
|
||||
}
|
||||
else if (color.A == byte.MaxValue)
|
||||
{
|
||||
for (int num31 = 0; num31 != num12; num31 += num25)
|
||||
{
|
||||
int num32 = (int)((float)x + num24 * (float)num31);
|
||||
int num33 = y + num31;
|
||||
byte* ptr7 = (byte*)image.ImageData.ToPointer() + (nint)num33 * (nint)stride + (nint)num32 * (nint)num;
|
||||
ptr7[2] = color.R;
|
||||
ptr7[1] = color.G;
|
||||
*ptr7 = color.B;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int num34 = 0; num34 != num12; num34 += num25)
|
||||
{
|
||||
int num35 = (int)((float)x + num24 * (float)num34);
|
||||
int num36 = y + num34;
|
||||
byte* ptr8 = (byte*)image.ImageData.ToPointer() + (nint)num36 * (nint)stride + (nint)num35 * (nint)num;
|
||||
ptr8[2] = (byte)((num8 + num7 * ptr8[2]) / 255);
|
||||
ptr8[1] = (byte)((num9 + num7 * ptr8[1]) / 255);
|
||||
*ptr8 = (byte)((num10 + num7 * *ptr8) / 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Polygon(BitmapData imageData, List<IntPoint> points, Color color)
|
||||
{
|
||||
Polygon(new UnmanagedImage(imageData), points, color);
|
||||
}
|
||||
|
||||
public static void Polygon(UnmanagedImage image, List<IntPoint> points, Color color)
|
||||
{
|
||||
int i = 1;
|
||||
for (int count = points.Count; i < count; i++)
|
||||
{
|
||||
Line(image, points[i - 1], points[i], color);
|
||||
}
|
||||
Line(image, points[points.Count - 1], points[0], color);
|
||||
}
|
||||
|
||||
public static void Polyline(BitmapData imageData, List<IntPoint> points, Color color)
|
||||
{
|
||||
Polyline(new UnmanagedImage(imageData), points, color);
|
||||
}
|
||||
|
||||
public static void Polyline(UnmanagedImage image, List<IntPoint> points, Color color)
|
||||
{
|
||||
int i = 1;
|
||||
for (int count = points.Count; i < count; i++)
|
||||
{
|
||||
Line(image, points[i - 1], points[i], color);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckPixelFormat(PixelFormat format)
|
||||
{
|
||||
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0006: Invalid comparison between Unknown and I4
|
||||
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000e: Invalid comparison between Unknown and I4
|
||||
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0016: Invalid comparison between Unknown and I4
|
||||
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001e: Invalid comparison between Unknown and I4
|
||||
if ((int)format != 137224 && (int)format != 198659 && (int)format != 2498570 && (int)format != 139273)
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Unsupported pixel format of the source image.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckEndPoint(int width, int height, IntPoint start, ref IntPoint end)
|
||||
{
|
||||
if (end.X >= width)
|
||||
{
|
||||
int num = width - 1;
|
||||
double num2 = (double)(num - start.X) / (double)(end.X - start.X);
|
||||
end.Y = (int)((double)start.Y + num2 * (double)(end.Y - start.Y));
|
||||
end.X = num;
|
||||
}
|
||||
if (end.Y >= height)
|
||||
{
|
||||
int num3 = height - 1;
|
||||
double num4 = (double)(num3 - start.Y) / (double)(end.Y - start.Y);
|
||||
end.X = (int)((double)start.X + num4 * (double)(end.X - start.X));
|
||||
end.Y = num3;
|
||||
}
|
||||
if (end.X < 0)
|
||||
{
|
||||
double num5 = (double)(-start.X) / (double)(end.X - start.X);
|
||||
end.Y = (int)((double)start.Y + num5 * (double)(end.Y - start.Y));
|
||||
end.X = 0;
|
||||
}
|
||||
if (end.Y < 0)
|
||||
{
|
||||
double num6 = (double)(-start.Y) / (double)(end.Y - start.Y);
|
||||
end.X = (int)((double)start.X + num6 * (double)(end.X - start.X));
|
||||
end.Y = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace AForge.Imaging;
|
||||
|
||||
internal static class ExceptionMessage
|
||||
{
|
||||
public const string ColorHistogramException = "Cannot access color histogram since the last processed image was grayscale.";
|
||||
|
||||
public const string GrayHistogramException = "Cannot access gray histogram since the last processed image was color.";
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging;
|
||||
|
||||
public class ExhaustiveBlockMatching : IBlockMatching
|
||||
{
|
||||
private class MatchingsSorter : IComparer<BlockMatch>
|
||||
{
|
||||
public int Compare(BlockMatch x, BlockMatch y)
|
||||
{
|
||||
float num = y.Similarity - x.Similarity;
|
||||
if (!(num > 0f))
|
||||
{
|
||||
if (!(num < 0f))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private int blockSize = 16;
|
||||
|
||||
private int searchRadius = 12;
|
||||
|
||||
private float similarityThreshold = 0.9f;
|
||||
|
||||
public int SearchRadius
|
||||
{
|
||||
get
|
||||
{
|
||||
return searchRadius;
|
||||
}
|
||||
set
|
||||
{
|
||||
searchRadius = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int BlockSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return blockSize;
|
||||
}
|
||||
set
|
||||
{
|
||||
blockSize = value;
|
||||
}
|
||||
}
|
||||
|
||||
public float SimilarityThreshold
|
||||
{
|
||||
get
|
||||
{
|
||||
return similarityThreshold;
|
||||
}
|
||||
set
|
||||
{
|
||||
similarityThreshold = System.Math.Min(1f, System.Math.Max(0f, value));
|
||||
}
|
||||
}
|
||||
|
||||
public ExhaustiveBlockMatching()
|
||||
{
|
||||
}
|
||||
|
||||
public ExhaustiveBlockMatching(int blockSize, int searchRadius)
|
||||
{
|
||||
this.blockSize = blockSize;
|
||||
this.searchRadius = searchRadius;
|
||||
}
|
||||
|
||||
public List<BlockMatch> ProcessImage(Bitmap sourceImage, List<IntPoint> coordinates, Bitmap searchImage)
|
||||
{
|
||||
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
|
||||
BitmapData val = sourceImage.LockBits(new Rectangle(0, 0, ((Image)sourceImage).Width, ((Image)sourceImage).Height), (ImageLockMode)1, ((Image)sourceImage).PixelFormat);
|
||||
BitmapData val2 = searchImage.LockBits(new Rectangle(0, 0, ((Image)searchImage).Width, ((Image)searchImage).Height), (ImageLockMode)1, ((Image)searchImage).PixelFormat);
|
||||
try
|
||||
{
|
||||
return ProcessImage(new UnmanagedImage(val), coordinates, new UnmanagedImage(val2));
|
||||
}
|
||||
finally
|
||||
{
|
||||
sourceImage.UnlockBits(val);
|
||||
searchImage.UnlockBits(val2);
|
||||
}
|
||||
}
|
||||
|
||||
public List<BlockMatch> ProcessImage(BitmapData sourceImageData, List<IntPoint> coordinates, BitmapData searchImageData)
|
||||
{
|
||||
return ProcessImage(new UnmanagedImage(sourceImageData), coordinates, new UnmanagedImage(searchImageData));
|
||||
}
|
||||
|
||||
public unsafe List<BlockMatch> ProcessImage(UnmanagedImage sourceImage, List<IntPoint> coordinates, UnmanagedImage searchImage)
|
||||
{
|
||||
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0032: Invalid comparison between Unknown and I4
|
||||
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_003f: Invalid comparison between Unknown and I4
|
||||
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0093: Invalid comparison between Unknown and I4
|
||||
if (sourceImage.Width != searchImage.Width || sourceImage.Height != searchImage.Height)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Source and search images sizes must match");
|
||||
}
|
||||
if ((int)sourceImage.PixelFormat != 198659 && (int)sourceImage.PixelFormat != 137224)
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Source images can be graysclae (8 bpp indexed) or color (24 bpp) image only");
|
||||
}
|
||||
if (sourceImage.PixelFormat != searchImage.PixelFormat)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Source and search images must have same pixel format");
|
||||
}
|
||||
int count = coordinates.Count;
|
||||
List<BlockMatch> list = new List<BlockMatch>();
|
||||
int width = sourceImage.Width;
|
||||
int height = sourceImage.Height;
|
||||
int stride = sourceImage.Stride;
|
||||
int num = (((int)sourceImage.PixelFormat == 198659) ? 1 : 3);
|
||||
int num2 = blockSize / 2;
|
||||
int num3 = 2 * searchRadius;
|
||||
int num4 = blockSize * num;
|
||||
int num5 = stride - blockSize * num;
|
||||
int num6 = blockSize * blockSize * num * 255;
|
||||
int num7 = (int)(similarityThreshold * (float)num6);
|
||||
byte* ptr = (byte*)sourceImage.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)searchImage.ImageData.ToPointer();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int x = coordinates[i].X;
|
||||
int y = coordinates[i].Y;
|
||||
if (x - num2 < 0 || x + num2 >= width || y - num2 < 0 || y + num2 >= height)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int num8 = x - num2 - searchRadius;
|
||||
int num9 = y - num2 - searchRadius;
|
||||
int x2 = x;
|
||||
int y2 = y;
|
||||
int num10 = int.MaxValue;
|
||||
for (int j = 0; j < num3; j++)
|
||||
{
|
||||
if (num9 + j < 0 || num9 + j + blockSize >= height)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (int k = 0; k < num3; k++)
|
||||
{
|
||||
int num11 = num8 + k;
|
||||
int num12 = num9 + j;
|
||||
if (num11 < 0 || num12 + blockSize >= width)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
byte* ptr3 = ptr + (nint)(y - num2) * (nint)stride + (nint)(x - num2) * (nint)num;
|
||||
byte* ptr4 = ptr2 + (nint)num12 * (nint)stride + (nint)num11 * (nint)num;
|
||||
int num13 = 0;
|
||||
for (int l = 0; l < blockSize; l++)
|
||||
{
|
||||
int num14 = 0;
|
||||
while (num14 < num4)
|
||||
{
|
||||
int num15 = *ptr3 - *ptr4;
|
||||
num13 = ((num15 <= 0) ? (num13 - num15) : (num13 + num15));
|
||||
num14++;
|
||||
ptr3++;
|
||||
ptr4++;
|
||||
}
|
||||
ptr3 += num5;
|
||||
ptr4 += num5;
|
||||
}
|
||||
if (num13 < num10)
|
||||
{
|
||||
num10 = num13;
|
||||
x2 = num11 + num2;
|
||||
y2 = num12 + num2;
|
||||
}
|
||||
}
|
||||
}
|
||||
int num16 = num6 - num10;
|
||||
if (num16 >= num7)
|
||||
{
|
||||
list.Add(new BlockMatch(new IntPoint(x, y), new IntPoint(x2, y2), (float)num16 / (float)num6));
|
||||
}
|
||||
}
|
||||
list.Sort(new MatchingsSorter());
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging;
|
||||
|
||||
public class ExhaustiveTemplateMatching : ITemplateMatching
|
||||
{
|
||||
private class MatchingsSorter : IComparer
|
||||
{
|
||||
public int Compare(object x, object y)
|
||||
{
|
||||
float num = ((TemplateMatch)y).Similarity - ((TemplateMatch)x).Similarity;
|
||||
if (!(num > 0f))
|
||||
{
|
||||
if (!(num < 0f))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private float similarityThreshold = 0.9f;
|
||||
|
||||
public float SimilarityThreshold
|
||||
{
|
||||
get
|
||||
{
|
||||
return similarityThreshold;
|
||||
}
|
||||
set
|
||||
{
|
||||
similarityThreshold = System.Math.Min(1f, System.Math.Max(0f, value));
|
||||
}
|
||||
}
|
||||
|
||||
public ExhaustiveTemplateMatching()
|
||||
{
|
||||
}
|
||||
|
||||
public ExhaustiveTemplateMatching(float similarityThreshold)
|
||||
{
|
||||
this.similarityThreshold = similarityThreshold;
|
||||
}
|
||||
|
||||
public TemplateMatch[] ProcessImage(Bitmap image, Bitmap template)
|
||||
{
|
||||
return ProcessImage(image, template, new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height));
|
||||
}
|
||||
|
||||
public TemplateMatch[] ProcessImage(Bitmap image, Bitmap template, Rectangle searchZone)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0018: Invalid comparison between Unknown and I4
|
||||
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (((int)((Image)image).PixelFormat != 198659 && (int)((Image)image).PixelFormat != 137224) || ((Image)image).PixelFormat != ((Image)template).PixelFormat)
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Unsupported pixel format of the source or template image.");
|
||||
}
|
||||
if (((Image)template).Width > ((Image)image).Width || ((Image)template).Height > ((Image)image).Height)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Template's size should be smaller or equal to source image's size.");
|
||||
}
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)1, ((Image)image).PixelFormat);
|
||||
BitmapData val2 = template.LockBits(new Rectangle(0, 0, ((Image)template).Width, ((Image)template).Height), (ImageLockMode)1, ((Image)template).PixelFormat);
|
||||
try
|
||||
{
|
||||
return ProcessImage(new UnmanagedImage(val), new UnmanagedImage(val2), searchZone);
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
template.UnlockBits(val2);
|
||||
}
|
||||
}
|
||||
|
||||
public TemplateMatch[] ProcessImage(BitmapData imageData, BitmapData templateData)
|
||||
{
|
||||
return ProcessImage(new UnmanagedImage(imageData), new UnmanagedImage(templateData), new Rectangle(0, 0, imageData.Width, imageData.Height));
|
||||
}
|
||||
|
||||
public TemplateMatch[] ProcessImage(BitmapData imageData, BitmapData templateData, Rectangle searchZone)
|
||||
{
|
||||
return ProcessImage(new UnmanagedImage(imageData), new UnmanagedImage(templateData), searchZone);
|
||||
}
|
||||
|
||||
public TemplateMatch[] ProcessImage(UnmanagedImage image, UnmanagedImage template)
|
||||
{
|
||||
return ProcessImage(image, template, new Rectangle(0, 0, image.Width, image.Height));
|
||||
}
|
||||
|
||||
public unsafe TemplateMatch[] ProcessImage(UnmanagedImage image, UnmanagedImage template, Rectangle searchZone)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0018: Invalid comparison between Unknown and I4
|
||||
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00a1: Invalid comparison between Unknown and I4
|
||||
if (((int)image.PixelFormat != 198659 && (int)image.PixelFormat != 137224) || image.PixelFormat != template.PixelFormat)
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Unsupported pixel format of the source or template image.");
|
||||
}
|
||||
Rectangle rectangle = searchZone;
|
||||
rectangle.Intersect(new Rectangle(0, 0, image.Width, image.Height));
|
||||
int x = rectangle.X;
|
||||
int y = rectangle.Y;
|
||||
int width = rectangle.Width;
|
||||
int height = rectangle.Height;
|
||||
int width2 = template.Width;
|
||||
int height2 = template.Height;
|
||||
if (width2 > width || height2 > height)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Template's size should be smaller or equal to search zone.");
|
||||
}
|
||||
int num = (((int)image.PixelFormat == 198659) ? 1 : 3);
|
||||
int stride = image.Stride;
|
||||
int num2 = width - width2 + 1;
|
||||
int num3 = height - height2 + 1;
|
||||
int[,] array = new int[num3 + 4, num2 + 4];
|
||||
int num4 = width2 * height2 * num * 255;
|
||||
int num5 = (int)(similarityThreshold * (float)num4);
|
||||
int num6 = width2 * num;
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)template.ImageData.ToPointer();
|
||||
int num7 = image.Stride - width2 * num;
|
||||
int num8 = template.Stride - width2 * num;
|
||||
for (int i = 0; i < num3; i++)
|
||||
{
|
||||
for (int j = 0; j < num2; j++)
|
||||
{
|
||||
byte* ptr3 = ptr + (nint)stride * (nint)(i + y) + (nint)num * (nint)(j + x);
|
||||
byte* ptr4 = ptr2;
|
||||
int num9 = 0;
|
||||
for (int k = 0; k < height2; k++)
|
||||
{
|
||||
int num10 = 0;
|
||||
while (num10 < num6)
|
||||
{
|
||||
int num11 = *ptr3 - *ptr4;
|
||||
num9 = ((num11 <= 0) ? (num9 - num11) : (num9 + num11));
|
||||
num10++;
|
||||
ptr3++;
|
||||
ptr4++;
|
||||
}
|
||||
ptr3 += num7;
|
||||
ptr4 += num8;
|
||||
}
|
||||
int num12 = num4 - num9;
|
||||
if (num12 >= num5)
|
||||
{
|
||||
array[i + 2, j + 2] = num12;
|
||||
}
|
||||
}
|
||||
}
|
||||
List<TemplateMatch> list = new List<TemplateMatch>();
|
||||
int l = 2;
|
||||
for (int num13 = num3 + 2; l < num13; l++)
|
||||
{
|
||||
int m = 2;
|
||||
for (int num14 = num2 + 2; m < num14; m++)
|
||||
{
|
||||
int num15 = array[l, m];
|
||||
int num16 = -2;
|
||||
while (num15 != 0 && num16 <= 2)
|
||||
{
|
||||
for (int n = -2; n <= 2; n++)
|
||||
{
|
||||
if (array[l + num16, m + n] > num15)
|
||||
{
|
||||
num15 = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
num16++;
|
||||
}
|
||||
if (num15 != 0)
|
||||
{
|
||||
list.Add(new TemplateMatch(new Rectangle(m - 2 + x, l - 2 + y, width2, height2), (float)num15 / (float)num4));
|
||||
}
|
||||
}
|
||||
}
|
||||
TemplateMatch[] array2 = new TemplateMatch[list.Count];
|
||||
list.CopyTo(array2);
|
||||
Array.Sort(array2, new MatchingsSorter());
|
||||
return array2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class AdaptiveSmoothing : BaseUsingCopyPartialFilter
|
||||
{
|
||||
private double factor = 3.0;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public double Factor
|
||||
{
|
||||
get
|
||||
{
|
||||
return factor;
|
||||
}
|
||||
set
|
||||
{
|
||||
factor = value;
|
||||
}
|
||||
}
|
||||
|
||||
public AdaptiveSmoothing()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
}
|
||||
|
||||
public AdaptiveSmoothing(double factor)
|
||||
: this()
|
||||
{
|
||||
this.factor = factor;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage source, UnmanagedImage destination, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
int num = Image.GetPixelFormatSize(source.PixelFormat) / 8;
|
||||
int num2 = num * 2;
|
||||
int left = rect.Left;
|
||||
int top = rect.Top;
|
||||
int num3 = left + rect.Width;
|
||||
int num4 = top + rect.Height;
|
||||
int num5 = left + 2;
|
||||
int num6 = top + 2;
|
||||
int num7 = num3 - 2;
|
||||
int num8 = num4 - 2;
|
||||
int stride = source.Stride;
|
||||
int stride2 = destination.Stride;
|
||||
int num9 = stride - rect.Width * num;
|
||||
int num10 = stride2 - rect.Width * num;
|
||||
double num11 = -8.0 * factor * factor;
|
||||
byte* ptr = (byte*)source.ImageData.ToPointer() + (nint)stride * (nint)2;
|
||||
byte* ptr2 = (byte*)destination.ImageData.ToPointer() + (nint)stride2 * (nint)2;
|
||||
ptr += top * stride + left * num;
|
||||
ptr2 += top * stride2 + left * num;
|
||||
for (int i = num6; i < num8; i++)
|
||||
{
|
||||
ptr += num2;
|
||||
ptr2 += num2;
|
||||
for (int j = num5; j < num7; j++)
|
||||
{
|
||||
int num12 = 0;
|
||||
while (num12 < num)
|
||||
{
|
||||
double num13 = 0.0;
|
||||
double num14 = 0.0;
|
||||
double num15 = ptr[-stride] - ptr[-num2 - stride];
|
||||
double num16 = ptr[-num] - ptr[-num - 2 * stride];
|
||||
double num17 = System.Math.Exp((num15 * num15 + num16 * num16) / num11);
|
||||
num14 += num17 * (double)(int)ptr[-num - stride];
|
||||
num13 += num17;
|
||||
num15 = ptr[num - stride] - ptr[-num - stride];
|
||||
num16 = *ptr - ptr[(nint)(-2) * (nint)stride];
|
||||
num17 = System.Math.Exp((num15 * num15 + num16 * num16) / num11);
|
||||
num14 += num17 * (double)(int)ptr[-stride];
|
||||
num13 += num17;
|
||||
num15 = ptr[num2 - stride] - ptr[-stride];
|
||||
num16 = ptr[num] - ptr[num - 2 * stride];
|
||||
num17 = System.Math.Exp((num15 * num15 + num16 * num16) / num11);
|
||||
num14 += num17 * (double)(int)ptr[num - stride];
|
||||
num13 += num17;
|
||||
num15 = *ptr - ptr[-num2];
|
||||
num16 = ptr[-num + stride] - ptr[-num - stride];
|
||||
num17 = System.Math.Exp((num15 * num15 + num16 * num16) / num11);
|
||||
num14 += num17 * (double)(int)ptr[-num];
|
||||
num13 += num17;
|
||||
num15 = ptr[num] - ptr[-num];
|
||||
num16 = ptr[stride] - ptr[-stride];
|
||||
num17 = System.Math.Exp((num15 * num15 + num16 * num16) / num11);
|
||||
num14 += num17 * (double)(int)(*ptr);
|
||||
num13 += num17;
|
||||
num15 = ptr[num2] - *ptr;
|
||||
num16 = ptr[num + stride] - ptr[num - stride];
|
||||
num17 = System.Math.Exp((num15 * num15 + num16 * num16) / num11);
|
||||
num14 += num17 * (double)(int)ptr[num];
|
||||
num13 += num17;
|
||||
num15 = ptr[stride] - ptr[-num2 + stride];
|
||||
num16 = ptr[-num + 2 * stride] - ptr[-num];
|
||||
num17 = System.Math.Exp((num15 * num15 + num16 * num16) / num11);
|
||||
num14 += num17 * (double)(int)ptr[-num + stride];
|
||||
num13 += num17;
|
||||
num15 = ptr[num + stride] - ptr[-num + stride];
|
||||
num16 = ptr[(nint)2 * (nint)stride] - *ptr;
|
||||
num17 = System.Math.Exp((num15 * num15 + num16 * num16) / num11);
|
||||
num14 += num17 * (double)(int)ptr[stride];
|
||||
num13 += num17;
|
||||
num15 = ptr[num2 + stride] - ptr[stride];
|
||||
num16 = ptr[num + 2 * stride] - ptr[num];
|
||||
num17 = System.Math.Exp((num15 * num15 + num16 * num16) / num11);
|
||||
num14 += num17 * (double)(int)ptr[num + stride];
|
||||
num13 += num17;
|
||||
*ptr2 = ((num13 == 0.0) ? (*ptr) : ((byte)System.Math.Min(num14 / num13, 255.0)));
|
||||
num12++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
}
|
||||
ptr += num9 + num2;
|
||||
ptr2 += num10 + num2;
|
||||
}
|
||||
}
|
||||
}
|
||||
109
output/Libraries/AForge.Imaging/AForge/Imaging/Filters/Add.cs
Normal file
109
output/Libraries/AForge.Imaging/AForge/Imaging/Filters/Add.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public sealed class Add : BaseInPlaceFilter2
|
||||
{
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public Add()
|
||||
{
|
||||
InitFormatTranslations();
|
||||
}
|
||||
|
||||
public Add(Bitmap overlayImage)
|
||||
: base(overlayImage)
|
||||
{
|
||||
InitFormatTranslations();
|
||||
}
|
||||
|
||||
public Add(UnmanagedImage unmanagedOverlayImage)
|
||||
: base(unmanagedOverlayImage)
|
||||
{
|
||||
InitFormatTranslations();
|
||||
}
|
||||
|
||||
private void InitFormatTranslations()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
formatTranslations[(PixelFormat)1052676] = (PixelFormat)1052676;
|
||||
formatTranslations[(PixelFormat)1060876] = (PixelFormat)1060876;
|
||||
formatTranslations[(PixelFormat)3424269] = (PixelFormat)3424269;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image, UnmanagedImage overlay)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001b: Invalid comparison between Unknown and I4
|
||||
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_003e: Invalid comparison between Unknown and I4
|
||||
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0023: Invalid comparison between Unknown and I4
|
||||
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0046: Invalid comparison between Unknown and I4
|
||||
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002b: Invalid comparison between Unknown and I4
|
||||
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0033: Invalid comparison between Unknown and I4
|
||||
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00f0: Invalid comparison between Unknown and I4
|
||||
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00f8: Invalid comparison between Unknown and I4
|
||||
PixelFormat pixelFormat = image.PixelFormat;
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
if ((int)pixelFormat == 198659 || (int)pixelFormat == 137224 || (int)pixelFormat == 139273 || (int)pixelFormat == 2498570)
|
||||
{
|
||||
int num = (((int)pixelFormat == 198659) ? 1 : (((int)pixelFormat == 137224) ? 3 : 4));
|
||||
int num2 = width * num;
|
||||
int num3 = image.Stride - num2;
|
||||
int num4 = overlay.Stride - num2;
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)overlay.ImageData.ToPointer();
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
int num5 = 0;
|
||||
while (num5 < num2)
|
||||
{
|
||||
int num6 = *ptr + *ptr2;
|
||||
*ptr = ((num6 > 255) ? byte.MaxValue : ((byte)num6));
|
||||
num5++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
ptr += num3;
|
||||
ptr2 += num4;
|
||||
}
|
||||
return;
|
||||
}
|
||||
int num7 = (((int)pixelFormat == 1052676) ? 1 : (((int)pixelFormat == 1060876) ? 3 : 4));
|
||||
int num8 = width * num7;
|
||||
int stride = image.Stride;
|
||||
int stride2 = overlay.Stride;
|
||||
byte* ptr3 = (byte*)image.ImageData.ToPointer();
|
||||
byte* ptr4 = (byte*)overlay.ImageData.ToPointer();
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
ushort* ptr5 = (ushort*)(ptr3 + (nint)j * (nint)stride);
|
||||
ushort* ptr6 = (ushort*)(ptr4 + (nint)j * (nint)stride2);
|
||||
int num9 = 0;
|
||||
while (num9 < num8)
|
||||
{
|
||||
int num10 = *ptr5 + *ptr6;
|
||||
*ptr5 = ((num10 > 65535) ? ushort.MaxValue : ((ushort)num10));
|
||||
num9++;
|
||||
ptr5++;
|
||||
ptr6++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using AForge.Math.Random;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class AdditiveNoise : BaseInPlacePartialFilter
|
||||
{
|
||||
private IRandomNumberGenerator generator = new UniformGenerator(new Range(-10f, 10f));
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public IRandomNumberGenerator Generator
|
||||
{
|
||||
get
|
||||
{
|
||||
return generator;
|
||||
}
|
||||
set
|
||||
{
|
||||
generator = value;
|
||||
}
|
||||
}
|
||||
|
||||
public AdditiveNoise()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
}
|
||||
|
||||
public AdditiveNoise(IRandomNumberGenerator generator)
|
||||
: this()
|
||||
{
|
||||
this.generator = generator;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
int num = (((int)image.PixelFormat == 198659) ? 1 : 3);
|
||||
int top = rect.Top;
|
||||
int num2 = top + rect.Height;
|
||||
int num3 = rect.Left * num;
|
||||
int num4 = num3 + rect.Width * num;
|
||||
int num5 = image.Stride - (num4 - num3);
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
ptr += top * image.Stride + rect.Left * num;
|
||||
for (int i = top; i < num2; i++)
|
||||
{
|
||||
int num6 = num3;
|
||||
while (num6 < num4)
|
||||
{
|
||||
*ptr = (byte)System.Math.Max(0f, System.Math.Min(255f, (float)(int)(*ptr) + generator.Next()));
|
||||
num6++;
|
||||
ptr++;
|
||||
}
|
||||
ptr += num5;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,308 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class ApplyMask : BaseInPlacePartialFilter
|
||||
{
|
||||
private Bitmap maskImage;
|
||||
|
||||
private UnmanagedImage unmanagedMaskImage;
|
||||
|
||||
private byte[,] mask;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public Bitmap MaskImage
|
||||
{
|
||||
get
|
||||
{
|
||||
return maskImage;
|
||||
}
|
||||
set
|
||||
{
|
||||
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0018: Invalid comparison between Unknown and I4
|
||||
if (maskImage != null && (int)((Image)maskImage).PixelFormat != 198659)
|
||||
{
|
||||
throw new ArgumentException("The mask image must be 8 bpp grayscale image.");
|
||||
}
|
||||
maskImage = value;
|
||||
unmanagedMaskImage = null;
|
||||
mask = null;
|
||||
}
|
||||
}
|
||||
|
||||
public UnmanagedImage UnmanagedMaskImage
|
||||
{
|
||||
get
|
||||
{
|
||||
return unmanagedMaskImage;
|
||||
}
|
||||
set
|
||||
{
|
||||
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0018: Invalid comparison between Unknown and I4
|
||||
if (unmanagedMaskImage != null && (int)unmanagedMaskImage.PixelFormat != 198659)
|
||||
{
|
||||
throw new ArgumentException("The mask image must be 8 bpp grayscale image.");
|
||||
}
|
||||
unmanagedMaskImage = value;
|
||||
maskImage = null;
|
||||
mask = null;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[,] Mask
|
||||
{
|
||||
get
|
||||
{
|
||||
return mask;
|
||||
}
|
||||
set
|
||||
{
|
||||
mask = value;
|
||||
maskImage = null;
|
||||
unmanagedMaskImage = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
private ApplyMask()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)925707] = (PixelFormat)925707;
|
||||
formatTranslations[(PixelFormat)1052676] = (PixelFormat)1052676;
|
||||
formatTranslations[(PixelFormat)1060876] = (PixelFormat)1060876;
|
||||
formatTranslations[(PixelFormat)3424269] = (PixelFormat)3424269;
|
||||
formatTranslations[(PixelFormat)1851406] = (PixelFormat)1851406;
|
||||
}
|
||||
|
||||
public ApplyMask(Bitmap maskImage)
|
||||
: this()
|
||||
{
|
||||
MaskImage = maskImage;
|
||||
}
|
||||
|
||||
public ApplyMask(UnmanagedImage unmanagedMaskImage)
|
||||
: this()
|
||||
{
|
||||
UnmanagedMaskImage = unmanagedMaskImage;
|
||||
}
|
||||
|
||||
public ApplyMask(byte[,] mask)
|
||||
: this()
|
||||
{
|
||||
Mask = mask;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
if (mask != null)
|
||||
{
|
||||
if (image.Width != mask.GetLength(1) || image.Height != mask.GetLength(0))
|
||||
{
|
||||
throw new ArgumentException("Invalid size of mask array. Its size must be the same as the size of the image to mask.");
|
||||
}
|
||||
fixed (byte* ptr = mask)
|
||||
{
|
||||
ProcessImage(image, rect, ptr, mask.GetLength(1));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (unmanagedMaskImage != null)
|
||||
{
|
||||
if (image.Width != unmanagedMaskImage.Width || image.Height != unmanagedMaskImage.Height)
|
||||
{
|
||||
throw new ArgumentException("Invalid size of unmanaged mask image. Its size must be the same as the size of the image to mask.");
|
||||
}
|
||||
ProcessImage(image, rect, (byte*)unmanagedMaskImage.ImageData.ToPointer(), unmanagedMaskImage.Stride);
|
||||
return;
|
||||
}
|
||||
if (maskImage != null)
|
||||
{
|
||||
if (image.Width != ((Image)maskImage).Width || image.Height != ((Image)maskImage).Height)
|
||||
{
|
||||
throw new ArgumentException("Invalid size of mask image. Its size must be the same as the size of the image to mask.");
|
||||
}
|
||||
BitmapData val = maskImage.LockBits(new Rectangle(0, 0, image.Width, image.Height), (ImageLockMode)1, (PixelFormat)198659);
|
||||
try
|
||||
{
|
||||
ProcessImage(image, rect, (byte*)val.Scan0.ToPointer(), val.Stride);
|
||||
return;
|
||||
}
|
||||
finally
|
||||
{
|
||||
maskImage.UnlockBits(val);
|
||||
}
|
||||
}
|
||||
throw new NullReferenceException("None of the possible mask properties were set. Need to provide mask before applying the filter.");
|
||||
}
|
||||
|
||||
private unsafe void ProcessImage(UnmanagedImage image, Rectangle rect, byte* mask, int maskLineSize)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
int num = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
int top = rect.Top;
|
||||
int num2 = top + rect.Height;
|
||||
int left = rect.Left;
|
||||
int num3 = left + rect.Width;
|
||||
int stride = image.Stride;
|
||||
int num4 = maskLineSize - rect.Width;
|
||||
mask += maskLineSize * top + left;
|
||||
if (num <= 4 && num != 2)
|
||||
{
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer() + (nint)stride * (nint)top + (nint)num * (nint)left;
|
||||
int num5 = stride - rect.Width * num;
|
||||
switch (num)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
for (int j = top; j < num2; j++)
|
||||
{
|
||||
int num7 = left;
|
||||
while (num7 < num3)
|
||||
{
|
||||
if (*mask == 0)
|
||||
{
|
||||
*ptr = 0;
|
||||
}
|
||||
num7++;
|
||||
ptr++;
|
||||
mask++;
|
||||
}
|
||||
ptr += num5;
|
||||
mask += num4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
for (int k = top; k < num2; k++)
|
||||
{
|
||||
int num8 = left;
|
||||
while (num8 < num3)
|
||||
{
|
||||
if (*mask == 0)
|
||||
{
|
||||
ptr[2] = 0;
|
||||
ptr[1] = 0;
|
||||
*ptr = 0;
|
||||
}
|
||||
num8++;
|
||||
ptr += 3;
|
||||
mask++;
|
||||
}
|
||||
ptr += num5;
|
||||
mask += num4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
for (int i = top; i < num2; i++)
|
||||
{
|
||||
int num6 = left;
|
||||
while (num6 < num3)
|
||||
{
|
||||
if (*mask == 0)
|
||||
{
|
||||
ptr[2] = 0;
|
||||
ptr[1] = 0;
|
||||
*ptr = 0;
|
||||
ptr[3] = 0;
|
||||
}
|
||||
num6++;
|
||||
ptr += 4;
|
||||
mask++;
|
||||
}
|
||||
ptr += num5;
|
||||
mask += num4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
byte* ptr2 = (byte*)image.ImageData.ToPointer() + (nint)stride * (nint)top + (nint)num * (nint)left;
|
||||
switch (num)
|
||||
{
|
||||
case 2:
|
||||
{
|
||||
for (int m = top; m < num2; m++)
|
||||
{
|
||||
ushort* ptr4 = (ushort*)ptr2;
|
||||
int num10 = left;
|
||||
while (num10 < num3)
|
||||
{
|
||||
if (*mask == 0)
|
||||
{
|
||||
*ptr4 = 0;
|
||||
}
|
||||
num10++;
|
||||
ptr4++;
|
||||
mask++;
|
||||
}
|
||||
ptr2 += stride;
|
||||
mask += num4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
for (int n = top; n < num2; n++)
|
||||
{
|
||||
ushort* ptr5 = (ushort*)ptr2;
|
||||
int num11 = left;
|
||||
while (num11 < num3)
|
||||
{
|
||||
if (*mask == 0)
|
||||
{
|
||||
ptr5[2] = 0;
|
||||
ptr5[1] = 0;
|
||||
*ptr5 = 0;
|
||||
}
|
||||
num11++;
|
||||
ptr5 += 3;
|
||||
mask++;
|
||||
}
|
||||
ptr2 += stride;
|
||||
mask += num4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
for (int l = top; l < num2; l++)
|
||||
{
|
||||
ushort* ptr3 = (ushort*)ptr2;
|
||||
int num9 = left;
|
||||
while (num9 < num3)
|
||||
{
|
||||
if (*mask == 0)
|
||||
{
|
||||
ptr3[2] = 0;
|
||||
ptr3[1] = 0;
|
||||
*ptr3 = 0;
|
||||
ptr3[3] = 0;
|
||||
}
|
||||
num9++;
|
||||
ptr3 += 4;
|
||||
mask++;
|
||||
}
|
||||
ptr2 += stride;
|
||||
mask += num4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using AForge.Math.Geometry;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class BackwardQuadrilateralTransformation : BaseInPlaceFilter
|
||||
{
|
||||
private Bitmap sourceImage;
|
||||
|
||||
private UnmanagedImage sourceUnmanagedImage;
|
||||
|
||||
private List<IntPoint> destinationQuadrilateral;
|
||||
|
||||
private bool useInterpolation = true;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public Bitmap SourceImage
|
||||
{
|
||||
get
|
||||
{
|
||||
return sourceImage;
|
||||
}
|
||||
set
|
||||
{
|
||||
sourceImage = value;
|
||||
if (value != null)
|
||||
{
|
||||
sourceUnmanagedImage = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public UnmanagedImage SourceUnmanagedImage
|
||||
{
|
||||
get
|
||||
{
|
||||
return sourceUnmanagedImage;
|
||||
}
|
||||
set
|
||||
{
|
||||
sourceUnmanagedImage = value;
|
||||
if (value != null)
|
||||
{
|
||||
sourceImage = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<IntPoint> DestinationQuadrilateral
|
||||
{
|
||||
get
|
||||
{
|
||||
return destinationQuadrilateral;
|
||||
}
|
||||
set
|
||||
{
|
||||
destinationQuadrilateral = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool UseInterpolation
|
||||
{
|
||||
get
|
||||
{
|
||||
return useInterpolation;
|
||||
}
|
||||
set
|
||||
{
|
||||
useInterpolation = value;
|
||||
}
|
||||
}
|
||||
|
||||
public BackwardQuadrilateralTransformation()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
formatTranslations[(PixelFormat)925707] = (PixelFormat)925707;
|
||||
}
|
||||
|
||||
public BackwardQuadrilateralTransformation(Bitmap sourceImage)
|
||||
: this()
|
||||
{
|
||||
this.sourceImage = sourceImage;
|
||||
}
|
||||
|
||||
public BackwardQuadrilateralTransformation(UnmanagedImage sourceUnmanagedImage)
|
||||
: this()
|
||||
{
|
||||
this.sourceUnmanagedImage = sourceUnmanagedImage;
|
||||
}
|
||||
|
||||
public BackwardQuadrilateralTransformation(Bitmap sourceImage, List<IntPoint> destinationQuadrilateral)
|
||||
: this()
|
||||
{
|
||||
this.sourceImage = sourceImage;
|
||||
this.destinationQuadrilateral = destinationQuadrilateral;
|
||||
}
|
||||
|
||||
public BackwardQuadrilateralTransformation(UnmanagedImage sourceUnmanagedImage, List<IntPoint> destinationQuadrilateral)
|
||||
: this()
|
||||
{
|
||||
this.sourceUnmanagedImage = sourceUnmanagedImage;
|
||||
this.destinationQuadrilateral = destinationQuadrilateral;
|
||||
}
|
||||
|
||||
protected override void ProcessFilter(UnmanagedImage image)
|
||||
{
|
||||
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (destinationQuadrilateral == null)
|
||||
{
|
||||
throw new NullReferenceException("Destination quadrilateral was not set.");
|
||||
}
|
||||
if (sourceImage != null)
|
||||
{
|
||||
if (image.PixelFormat != ((Image)sourceImage).PixelFormat)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Source and destination images must have same pixel format.");
|
||||
}
|
||||
BitmapData val = sourceImage.LockBits(new Rectangle(0, 0, ((Image)sourceImage).Width, ((Image)sourceImage).Height), (ImageLockMode)1, ((Image)sourceImage).PixelFormat);
|
||||
try
|
||||
{
|
||||
ProcessFilter(image, new UnmanagedImage(val));
|
||||
return;
|
||||
}
|
||||
finally
|
||||
{
|
||||
sourceImage.UnlockBits(val);
|
||||
}
|
||||
}
|
||||
if (sourceUnmanagedImage != null)
|
||||
{
|
||||
if (image.PixelFormat != sourceUnmanagedImage.PixelFormat)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Source and destination images must have same pixel format.");
|
||||
}
|
||||
ProcessFilter(image, sourceUnmanagedImage);
|
||||
return;
|
||||
}
|
||||
throw new NullReferenceException("Source image is not set.");
|
||||
}
|
||||
|
||||
private unsafe void ProcessFilter(UnmanagedImage dstImage, UnmanagedImage srcImage)
|
||||
{
|
||||
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
|
||||
int width = srcImage.Width;
|
||||
int height = srcImage.Height;
|
||||
int width2 = dstImage.Width;
|
||||
int height2 = dstImage.Height;
|
||||
int num = Image.GetPixelFormatSize(srcImage.PixelFormat) / 8;
|
||||
int stride = srcImage.Stride;
|
||||
int stride2 = dstImage.Stride;
|
||||
PointsCloud.GetBoundingRectangle(destinationQuadrilateral, out var minXY, out var maxXY);
|
||||
if (maxXY.X < 0 || maxXY.Y < 0 || minXY.X >= width2 || minXY.Y >= height2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (minXY.X < 0)
|
||||
{
|
||||
minXY.X = 0;
|
||||
}
|
||||
if (minXY.Y < 0)
|
||||
{
|
||||
minXY.Y = 0;
|
||||
}
|
||||
if (maxXY.X >= width2)
|
||||
{
|
||||
maxXY.X = width2 - 1;
|
||||
}
|
||||
if (maxXY.Y >= height2)
|
||||
{
|
||||
maxXY.Y = height2 - 1;
|
||||
}
|
||||
int x = minXY.X;
|
||||
int y = minXY.Y;
|
||||
int num2 = maxXY.X + 1;
|
||||
int num3 = maxXY.Y + 1;
|
||||
int num4 = stride2 - (num2 - x) * num;
|
||||
List<IntPoint> list = new List<IntPoint>();
|
||||
list.Add(new IntPoint(0, 0));
|
||||
list.Add(new IntPoint(width - 1, 0));
|
||||
list.Add(new IntPoint(width - 1, height - 1));
|
||||
list.Add(new IntPoint(0, height - 1));
|
||||
double[,] array = QuadTransformationCalcs.MapQuadToQuad(destinationQuadrilateral, list);
|
||||
byte* ptr = (byte*)dstImage.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)srcImage.ImageData.ToPointer();
|
||||
ptr += y * stride2 + x * num;
|
||||
if (!useInterpolation)
|
||||
{
|
||||
for (int i = y; i < num3; i++)
|
||||
{
|
||||
for (int j = x; j < num2; j++)
|
||||
{
|
||||
double num5 = array[2, 0] * (double)j + array[2, 1] * (double)i + array[2, 2];
|
||||
double num6 = (array[0, 0] * (double)j + array[0, 1] * (double)i + array[0, 2]) / num5;
|
||||
double num7 = (array[1, 0] * (double)j + array[1, 1] * (double)i + array[1, 2]) / num5;
|
||||
if (num6 >= 0.0 && num7 >= 0.0 && num6 < (double)width && num7 < (double)height)
|
||||
{
|
||||
byte* ptr3 = ptr2 + (nint)(int)num7 * (nint)stride + (nint)(int)num6 * (nint)num;
|
||||
int num8 = 0;
|
||||
while (num8 < num)
|
||||
{
|
||||
*ptr = *ptr3;
|
||||
num8++;
|
||||
ptr++;
|
||||
ptr3++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr += num;
|
||||
}
|
||||
}
|
||||
ptr += num4;
|
||||
}
|
||||
return;
|
||||
}
|
||||
int num9 = width - 1;
|
||||
int num10 = height - 1;
|
||||
for (int k = y; k < num3; k++)
|
||||
{
|
||||
for (int l = x; l < num2; l++)
|
||||
{
|
||||
double num11 = array[2, 0] * (double)l + array[2, 1] * (double)k + array[2, 2];
|
||||
double num12 = (array[0, 0] * (double)l + array[0, 1] * (double)k + array[0, 2]) / num11;
|
||||
double num13 = (array[1, 0] * (double)l + array[1, 1] * (double)k + array[1, 2]) / num11;
|
||||
if (num12 >= 0.0 && num13 >= 0.0 && num12 < (double)width && num13 < (double)height)
|
||||
{
|
||||
int num14 = (int)num12;
|
||||
int num15 = ((num14 == num9) ? num14 : (num14 + 1));
|
||||
double num16 = num12 - (double)num14;
|
||||
double num17 = 1.0 - num16;
|
||||
int num18 = (int)num13;
|
||||
int num19 = ((num18 == num10) ? num18 : (num18 + 1));
|
||||
double num20 = num13 - (double)num18;
|
||||
double num21 = 1.0 - num20;
|
||||
byte* ptr5;
|
||||
byte* ptr4 = (ptr5 = ptr2 + (nint)num18 * (nint)stride);
|
||||
ptr4 += (nint)num14 * (nint)num;
|
||||
ptr5 += (nint)num15 * (nint)num;
|
||||
byte* ptr7;
|
||||
byte* ptr6 = (ptr7 = ptr2 + (nint)num19 * (nint)stride);
|
||||
ptr6 += (nint)num14 * (nint)num;
|
||||
ptr7 += (nint)num15 * (nint)num;
|
||||
int num22 = 0;
|
||||
while (num22 < num)
|
||||
{
|
||||
*ptr = (byte)(num21 * (num17 * (double)(int)(*ptr4) + num16 * (double)(int)(*ptr5)) + num20 * (num17 * (double)(int)(*ptr6) + num16 * (double)(int)(*ptr7)));
|
||||
num22++;
|
||||
ptr++;
|
||||
ptr4++;
|
||||
ptr5++;
|
||||
ptr6++;
|
||||
ptr7++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr += num;
|
||||
}
|
||||
}
|
||||
ptr += num4;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public abstract class BaseFilter : IFilter, IFilterInformation
|
||||
{
|
||||
public abstract Dictionary<PixelFormat, PixelFormat> FormatTranslations { get; }
|
||||
|
||||
public Bitmap Apply(Bitmap image)
|
||||
{
|
||||
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)1, ((Image)image).PixelFormat);
|
||||
Bitmap val2 = null;
|
||||
try
|
||||
{
|
||||
val2 = Apply(val);
|
||||
if (((Image)image).HorizontalResolution > 0f && ((Image)image).VerticalResolution > 0f)
|
||||
{
|
||||
val2.SetResolution(((Image)image).HorizontalResolution, ((Image)image).VerticalResolution);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
}
|
||||
return val2;
|
||||
}
|
||||
|
||||
public Bitmap Apply(BitmapData imageData)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0032: Invalid comparison between Unknown and I4
|
||||
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(imageData.PixelFormat);
|
||||
int width = imageData.Width;
|
||||
int height = imageData.Height;
|
||||
PixelFormat val = FormatTranslations[imageData.PixelFormat];
|
||||
Bitmap val2 = (Bitmap)(((int)val == 198659) ? ((object)Image.CreateGrayscaleImage(width, height)) : ((object)new Bitmap(width, height, val)));
|
||||
BitmapData val3 = val2.LockBits(new Rectangle(0, 0, width, height), (ImageLockMode)3, val);
|
||||
try
|
||||
{
|
||||
ProcessFilter(new UnmanagedImage(imageData), new UnmanagedImage(val3));
|
||||
}
|
||||
finally
|
||||
{
|
||||
val2.UnlockBits(val3);
|
||||
}
|
||||
return val2;
|
||||
}
|
||||
|
||||
public UnmanagedImage Apply(UnmanagedImage image)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(image.PixelFormat);
|
||||
UnmanagedImage unmanagedImage = UnmanagedImage.Create(image.Width, image.Height, FormatTranslations[image.PixelFormat]);
|
||||
ProcessFilter(image, unmanagedImage);
|
||||
return unmanagedImage;
|
||||
}
|
||||
|
||||
public void Apply(UnmanagedImage sourceImage, UnmanagedImage destinationImage)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(sourceImage.PixelFormat);
|
||||
if (destinationImage.PixelFormat != FormatTranslations[sourceImage.PixelFormat])
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Destination pixel format is specified incorrectly.");
|
||||
}
|
||||
if (destinationImage.Width != sourceImage.Width || destinationImage.Height != sourceImage.Height)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Destination image must have the same width and height as source image.");
|
||||
}
|
||||
ProcessFilter(sourceImage, destinationImage);
|
||||
}
|
||||
|
||||
protected abstract void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData);
|
||||
|
||||
private void CheckSourceFormat(PixelFormat pixelFormat)
|
||||
{
|
||||
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (!FormatTranslations.ContainsKey(pixelFormat))
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Source pixel format is not supported by the filter.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public abstract class BaseFilter2 : BaseFilter
|
||||
{
|
||||
private Bitmap overlayImage;
|
||||
|
||||
private UnmanagedImage unmanagedOverlayImage;
|
||||
|
||||
public Bitmap OverlayImage
|
||||
{
|
||||
get
|
||||
{
|
||||
return overlayImage;
|
||||
}
|
||||
set
|
||||
{
|
||||
overlayImage = value;
|
||||
if (value != null)
|
||||
{
|
||||
unmanagedOverlayImage = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public UnmanagedImage UnmanagedOverlayImage
|
||||
{
|
||||
get
|
||||
{
|
||||
return unmanagedOverlayImage;
|
||||
}
|
||||
set
|
||||
{
|
||||
unmanagedOverlayImage = value;
|
||||
if (value != null)
|
||||
{
|
||||
overlayImage = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected BaseFilter2()
|
||||
{
|
||||
}
|
||||
|
||||
protected BaseFilter2(Bitmap overlayImage)
|
||||
{
|
||||
this.overlayImage = overlayImage;
|
||||
}
|
||||
|
||||
protected BaseFilter2(UnmanagedImage unmanagedOverlayImage)
|
||||
{
|
||||
this.unmanagedOverlayImage = unmanagedOverlayImage;
|
||||
}
|
||||
|
||||
protected override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
|
||||
PixelFormat pixelFormat = sourceData.PixelFormat;
|
||||
int width = sourceData.Width;
|
||||
int height = sourceData.Height;
|
||||
if (overlayImage != null)
|
||||
{
|
||||
if (pixelFormat != ((Image)overlayImage).PixelFormat)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Source and overlay images must have same pixel format.");
|
||||
}
|
||||
if (width != ((Image)overlayImage).Width || height != ((Image)overlayImage).Height)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Overlay image size must be equal to source image size.");
|
||||
}
|
||||
BitmapData val = overlayImage.LockBits(new Rectangle(0, 0, width, height), (ImageLockMode)1, pixelFormat);
|
||||
try
|
||||
{
|
||||
ProcessFilter(sourceData, new UnmanagedImage(val), destinationData);
|
||||
return;
|
||||
}
|
||||
finally
|
||||
{
|
||||
overlayImage.UnlockBits(val);
|
||||
}
|
||||
}
|
||||
if (unmanagedOverlayImage != null)
|
||||
{
|
||||
if (pixelFormat != unmanagedOverlayImage.PixelFormat)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Source and overlay images must have same pixel format.");
|
||||
}
|
||||
if (width != unmanagedOverlayImage.Width || height != unmanagedOverlayImage.Height)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Overlay image size must be equal to source image size.");
|
||||
}
|
||||
ProcessFilter(sourceData, unmanagedOverlayImage, destinationData);
|
||||
return;
|
||||
}
|
||||
throw new NullReferenceException("Overlay image is not set.");
|
||||
}
|
||||
|
||||
protected abstract void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage overlay, UnmanagedImage destinationData);
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public abstract class BaseInPlaceFilter : IFilter, IInPlaceFilter, IFilterInformation
|
||||
{
|
||||
public abstract Dictionary<PixelFormat, PixelFormat> FormatTranslations { get; }
|
||||
|
||||
public Bitmap Apply(Bitmap image)
|
||||
{
|
||||
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)1, ((Image)image).PixelFormat);
|
||||
Bitmap val2 = null;
|
||||
try
|
||||
{
|
||||
val2 = Apply(val);
|
||||
if (((Image)image).HorizontalResolution > 0f && ((Image)image).VerticalResolution > 0f)
|
||||
{
|
||||
val2.SetResolution(((Image)image).HorizontalResolution, ((Image)image).VerticalResolution);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
}
|
||||
return val2;
|
||||
}
|
||||
|
||||
public Bitmap Apply(BitmapData imageData)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0022: Invalid comparison between Unknown and I4
|
||||
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
|
||||
PixelFormat pixelFormat = imageData.PixelFormat;
|
||||
CheckSourceFormat(pixelFormat);
|
||||
int width = imageData.Width;
|
||||
int height = imageData.Height;
|
||||
Bitmap val = (Bitmap)(((int)pixelFormat == 198659) ? ((object)Image.CreateGrayscaleImage(width, height)) : ((object)new Bitmap(width, height, pixelFormat)));
|
||||
BitmapData val2 = val.LockBits(new Rectangle(0, 0, width, height), (ImageLockMode)3, pixelFormat);
|
||||
SystemTools.CopyUnmanagedMemory(val2.Scan0, imageData.Scan0, imageData.Stride * height);
|
||||
try
|
||||
{
|
||||
ProcessFilter(new UnmanagedImage(val2));
|
||||
}
|
||||
finally
|
||||
{
|
||||
val.UnlockBits(val2);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
public UnmanagedImage Apply(UnmanagedImage image)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(image.PixelFormat);
|
||||
UnmanagedImage unmanagedImage = UnmanagedImage.Create(image.Width, image.Height, image.PixelFormat);
|
||||
Apply(image, unmanagedImage);
|
||||
return unmanagedImage;
|
||||
}
|
||||
|
||||
public unsafe void Apply(UnmanagedImage sourceImage, UnmanagedImage destinationImage)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(sourceImage.PixelFormat);
|
||||
if (destinationImage.PixelFormat != sourceImage.PixelFormat)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Destination pixel format must be the same as pixel format of source image.");
|
||||
}
|
||||
if (destinationImage.Width != sourceImage.Width || destinationImage.Height != sourceImage.Height)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Destination image must have the same width and height as source image.");
|
||||
}
|
||||
int stride = destinationImage.Stride;
|
||||
int stride2 = sourceImage.Stride;
|
||||
int count = System.Math.Min(stride2, stride);
|
||||
byte* ptr = (byte*)destinationImage.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)sourceImage.ImageData.ToPointer();
|
||||
int i = 0;
|
||||
for (int height = sourceImage.Height; i < height; i++)
|
||||
{
|
||||
SystemTools.CopyUnmanagedMemory(ptr, ptr2, count);
|
||||
ptr += stride;
|
||||
ptr2 += stride2;
|
||||
}
|
||||
ProcessFilter(destinationImage);
|
||||
}
|
||||
|
||||
public void ApplyInPlace(Bitmap image)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(((Image)image).PixelFormat);
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)3, ((Image)image).PixelFormat);
|
||||
try
|
||||
{
|
||||
ProcessFilter(new UnmanagedImage(val));
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyInPlace(BitmapData imageData)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(imageData.PixelFormat);
|
||||
ProcessFilter(new UnmanagedImage(imageData));
|
||||
}
|
||||
|
||||
public void ApplyInPlace(UnmanagedImage image)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(image.PixelFormat);
|
||||
ProcessFilter(image);
|
||||
}
|
||||
|
||||
protected abstract void ProcessFilter(UnmanagedImage image);
|
||||
|
||||
private void CheckSourceFormat(PixelFormat pixelFormat)
|
||||
{
|
||||
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (!FormatTranslations.ContainsKey(pixelFormat))
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Source pixel format is not supported by the filter.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public abstract class BaseInPlaceFilter2 : BaseInPlaceFilter
|
||||
{
|
||||
private Bitmap overlayImage;
|
||||
|
||||
private UnmanagedImage unmanagedOverlayImage;
|
||||
|
||||
public Bitmap OverlayImage
|
||||
{
|
||||
get
|
||||
{
|
||||
return overlayImage;
|
||||
}
|
||||
set
|
||||
{
|
||||
overlayImage = value;
|
||||
if (value != null)
|
||||
{
|
||||
unmanagedOverlayImage = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public UnmanagedImage UnmanagedOverlayImage
|
||||
{
|
||||
get
|
||||
{
|
||||
return unmanagedOverlayImage;
|
||||
}
|
||||
set
|
||||
{
|
||||
unmanagedOverlayImage = value;
|
||||
if (value != null)
|
||||
{
|
||||
overlayImage = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected BaseInPlaceFilter2()
|
||||
{
|
||||
}
|
||||
|
||||
protected BaseInPlaceFilter2(Bitmap overlayImage)
|
||||
{
|
||||
this.overlayImage = overlayImage;
|
||||
}
|
||||
|
||||
protected BaseInPlaceFilter2(UnmanagedImage unmanagedOverlayImage)
|
||||
{
|
||||
this.unmanagedOverlayImage = unmanagedOverlayImage;
|
||||
}
|
||||
|
||||
protected override void ProcessFilter(UnmanagedImage image)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
|
||||
PixelFormat pixelFormat = image.PixelFormat;
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
if (overlayImage != null)
|
||||
{
|
||||
if (pixelFormat != ((Image)overlayImage).PixelFormat)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Source and overlay images must have same pixel format.");
|
||||
}
|
||||
if (width != ((Image)overlayImage).Width || height != ((Image)overlayImage).Height)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Overlay image size must be equal to source image size.");
|
||||
}
|
||||
BitmapData val = overlayImage.LockBits(new Rectangle(0, 0, width, height), (ImageLockMode)1, pixelFormat);
|
||||
try
|
||||
{
|
||||
ProcessFilter(image, new UnmanagedImage(val));
|
||||
return;
|
||||
}
|
||||
finally
|
||||
{
|
||||
overlayImage.UnlockBits(val);
|
||||
}
|
||||
}
|
||||
if (unmanagedOverlayImage != null)
|
||||
{
|
||||
if (pixelFormat != unmanagedOverlayImage.PixelFormat)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Source and overlay images must have same pixel format.");
|
||||
}
|
||||
if (width != unmanagedOverlayImage.Width || height != unmanagedOverlayImage.Height)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Overlay image size must be equal to source image size.");
|
||||
}
|
||||
ProcessFilter(image, unmanagedOverlayImage);
|
||||
return;
|
||||
}
|
||||
throw new NullReferenceException("Overlay image is not set.");
|
||||
}
|
||||
|
||||
protected abstract void ProcessFilter(UnmanagedImage image, UnmanagedImage overlay);
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public abstract class BaseInPlacePartialFilter : IFilter, IInPlaceFilter, IInPlacePartialFilter, IFilterInformation
|
||||
{
|
||||
public abstract Dictionary<PixelFormat, PixelFormat> FormatTranslations { get; }
|
||||
|
||||
public Bitmap Apply(Bitmap image)
|
||||
{
|
||||
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)1, ((Image)image).PixelFormat);
|
||||
Bitmap val2 = null;
|
||||
try
|
||||
{
|
||||
val2 = Apply(val);
|
||||
if (((Image)image).HorizontalResolution > 0f && ((Image)image).VerticalResolution > 0f)
|
||||
{
|
||||
val2.SetResolution(((Image)image).HorizontalResolution, ((Image)image).VerticalResolution);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
}
|
||||
return val2;
|
||||
}
|
||||
|
||||
public Bitmap Apply(BitmapData imageData)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0022: Invalid comparison between Unknown and I4
|
||||
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
|
||||
PixelFormat pixelFormat = imageData.PixelFormat;
|
||||
CheckSourceFormat(pixelFormat);
|
||||
int width = imageData.Width;
|
||||
int height = imageData.Height;
|
||||
Bitmap val = (Bitmap)(((int)pixelFormat == 198659) ? ((object)Image.CreateGrayscaleImage(width, height)) : ((object)new Bitmap(width, height, pixelFormat)));
|
||||
BitmapData val2 = val.LockBits(new Rectangle(0, 0, width, height), (ImageLockMode)3, pixelFormat);
|
||||
SystemTools.CopyUnmanagedMemory(val2.Scan0, imageData.Scan0, imageData.Stride * height);
|
||||
try
|
||||
{
|
||||
ProcessFilter(new UnmanagedImage(val2), new Rectangle(0, 0, width, height));
|
||||
}
|
||||
finally
|
||||
{
|
||||
val.UnlockBits(val2);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
public UnmanagedImage Apply(UnmanagedImage image)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(image.PixelFormat);
|
||||
UnmanagedImage unmanagedImage = UnmanagedImage.Create(image.Width, image.Height, image.PixelFormat);
|
||||
Apply(image, unmanagedImage);
|
||||
return unmanagedImage;
|
||||
}
|
||||
|
||||
public unsafe void Apply(UnmanagedImage sourceImage, UnmanagedImage destinationImage)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(sourceImage.PixelFormat);
|
||||
if (destinationImage.PixelFormat != sourceImage.PixelFormat)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Destination pixel format must be the same as pixel format of source image.");
|
||||
}
|
||||
if (destinationImage.Width != sourceImage.Width || destinationImage.Height != sourceImage.Height)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Destination image must have the same width and height as source image.");
|
||||
}
|
||||
int stride = destinationImage.Stride;
|
||||
int stride2 = sourceImage.Stride;
|
||||
int count = System.Math.Min(stride2, stride);
|
||||
byte* ptr = (byte*)destinationImage.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)sourceImage.ImageData.ToPointer();
|
||||
int i = 0;
|
||||
for (int height = sourceImage.Height; i < height; i++)
|
||||
{
|
||||
SystemTools.CopyUnmanagedMemory(ptr, ptr2, count);
|
||||
ptr += stride;
|
||||
ptr2 += stride2;
|
||||
}
|
||||
ProcessFilter(destinationImage, new Rectangle(0, 0, destinationImage.Width, destinationImage.Height));
|
||||
}
|
||||
|
||||
public void ApplyInPlace(Bitmap image)
|
||||
{
|
||||
ApplyInPlace(image, new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height));
|
||||
}
|
||||
|
||||
public void ApplyInPlace(BitmapData imageData)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(imageData.PixelFormat);
|
||||
ProcessFilter(new UnmanagedImage(imageData), new Rectangle(0, 0, imageData.Width, imageData.Height));
|
||||
}
|
||||
|
||||
public void ApplyInPlace(UnmanagedImage image)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(image.PixelFormat);
|
||||
ProcessFilter(image, new Rectangle(0, 0, image.Width, image.Height));
|
||||
}
|
||||
|
||||
public void ApplyInPlace(Bitmap image, Rectangle rect)
|
||||
{
|
||||
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)3, ((Image)image).PixelFormat);
|
||||
try
|
||||
{
|
||||
ApplyInPlace(new UnmanagedImage(val), rect);
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyInPlace(BitmapData imageData, Rectangle rect)
|
||||
{
|
||||
ApplyInPlace(new UnmanagedImage(imageData), rect);
|
||||
}
|
||||
|
||||
public void ApplyInPlace(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(image.PixelFormat);
|
||||
rect.Intersect(new Rectangle(0, 0, image.Width, image.Height));
|
||||
if ((rect.Width | rect.Height) != 0)
|
||||
{
|
||||
ProcessFilter(image, rect);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void ProcessFilter(UnmanagedImage image, Rectangle rect);
|
||||
|
||||
private void CheckSourceFormat(PixelFormat pixelFormat)
|
||||
{
|
||||
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (!FormatTranslations.ContainsKey(pixelFormat))
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Source pixel format is not supported by the filter.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public abstract class BaseResizeFilter : BaseTransformationFilter
|
||||
{
|
||||
protected int newWidth;
|
||||
|
||||
protected int newHeight;
|
||||
|
||||
public int NewWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return newWidth;
|
||||
}
|
||||
set
|
||||
{
|
||||
newWidth = System.Math.Max(1, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int NewHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
return newHeight;
|
||||
}
|
||||
set
|
||||
{
|
||||
newHeight = System.Math.Max(1, value);
|
||||
}
|
||||
}
|
||||
|
||||
protected BaseResizeFilter(int newWidth, int newHeight)
|
||||
{
|
||||
this.newWidth = newWidth;
|
||||
this.newHeight = newHeight;
|
||||
}
|
||||
|
||||
protected override Size CalculateNewImageSize(UnmanagedImage sourceData)
|
||||
{
|
||||
return new Size(newWidth, newHeight);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public abstract class BaseRotateFilter : BaseTransformationFilter
|
||||
{
|
||||
protected double angle;
|
||||
|
||||
protected bool keepSize;
|
||||
|
||||
protected Color fillColor = Color.FromArgb(0, 0, 0);
|
||||
|
||||
public double Angle
|
||||
{
|
||||
get
|
||||
{
|
||||
return angle;
|
||||
}
|
||||
set
|
||||
{
|
||||
angle = value % 360.0;
|
||||
}
|
||||
}
|
||||
|
||||
public bool KeepSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return keepSize;
|
||||
}
|
||||
set
|
||||
{
|
||||
keepSize = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Color FillColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return fillColor;
|
||||
}
|
||||
set
|
||||
{
|
||||
fillColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
public BaseRotateFilter(double angle)
|
||||
{
|
||||
this.angle = angle;
|
||||
}
|
||||
|
||||
public BaseRotateFilter(double angle, bool keepSize)
|
||||
{
|
||||
this.angle = angle;
|
||||
this.keepSize = keepSize;
|
||||
}
|
||||
|
||||
protected override Size CalculateNewImageSize(UnmanagedImage sourceData)
|
||||
{
|
||||
if (keepSize)
|
||||
{
|
||||
return new Size(sourceData.Width, sourceData.Height);
|
||||
}
|
||||
double num = (0.0 - angle) * System.Math.PI / 180.0;
|
||||
double num2 = System.Math.Cos(num);
|
||||
double num3 = System.Math.Sin(num);
|
||||
double num4 = (double)sourceData.Width / 2.0;
|
||||
double num5 = (double)sourceData.Height / 2.0;
|
||||
double val = num4 * num2;
|
||||
double val2 = num4 * num3;
|
||||
double val3 = num4 * num2 - num5 * num3;
|
||||
double val4 = num4 * num3 + num5 * num2;
|
||||
double val5 = (0.0 - num5) * num3;
|
||||
double val6 = num5 * num2;
|
||||
double val7 = 0.0;
|
||||
double val8 = 0.0;
|
||||
num4 = System.Math.Max(System.Math.Max(val, val3), System.Math.Max(val5, val7)) - System.Math.Min(System.Math.Min(val, val3), System.Math.Min(val5, val7));
|
||||
num5 = System.Math.Max(System.Math.Max(val2, val4), System.Math.Max(val6, val8)) - System.Math.Min(System.Math.Min(val2, val4), System.Math.Min(val6, val8));
|
||||
return new Size((int)(num4 * 2.0 + 0.5), (int)(num5 * 2.0 + 0.5));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public abstract class BaseTransformationFilter : IFilter, IFilterInformation
|
||||
{
|
||||
public abstract Dictionary<PixelFormat, PixelFormat> FormatTranslations { get; }
|
||||
|
||||
public Bitmap Apply(Bitmap image)
|
||||
{
|
||||
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)1, ((Image)image).PixelFormat);
|
||||
Bitmap val2 = null;
|
||||
try
|
||||
{
|
||||
val2 = Apply(val);
|
||||
if (((Image)image).HorizontalResolution > 0f && ((Image)image).VerticalResolution > 0f)
|
||||
{
|
||||
val2.SetResolution(((Image)image).HorizontalResolution, ((Image)image).VerticalResolution);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
}
|
||||
return val2;
|
||||
}
|
||||
|
||||
public Bitmap Apply(BitmapData imageData)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0031: Invalid comparison between Unknown and I4
|
||||
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(imageData.PixelFormat);
|
||||
PixelFormat val = FormatTranslations[imageData.PixelFormat];
|
||||
Size size = CalculateNewImageSize(new UnmanagedImage(imageData));
|
||||
Bitmap val2 = (Bitmap)(((int)val == 198659) ? ((object)Image.CreateGrayscaleImage(size.Width, size.Height)) : ((object)new Bitmap(size.Width, size.Height, val)));
|
||||
BitmapData val3 = val2.LockBits(new Rectangle(0, 0, size.Width, size.Height), (ImageLockMode)3, val);
|
||||
try
|
||||
{
|
||||
ProcessFilter(new UnmanagedImage(imageData), new UnmanagedImage(val3));
|
||||
}
|
||||
finally
|
||||
{
|
||||
val2.UnlockBits(val3);
|
||||
}
|
||||
return val2;
|
||||
}
|
||||
|
||||
public UnmanagedImage Apply(UnmanagedImage image)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(image.PixelFormat);
|
||||
Size size = CalculateNewImageSize(image);
|
||||
UnmanagedImage unmanagedImage = UnmanagedImage.Create(size.Width, size.Height, FormatTranslations[image.PixelFormat]);
|
||||
ProcessFilter(image, unmanagedImage);
|
||||
return unmanagedImage;
|
||||
}
|
||||
|
||||
public void Apply(UnmanagedImage sourceImage, UnmanagedImage destinationImage)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(sourceImage.PixelFormat);
|
||||
if (destinationImage.PixelFormat != FormatTranslations[sourceImage.PixelFormat])
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Destination pixel format is specified incorrectly.");
|
||||
}
|
||||
Size size = CalculateNewImageSize(sourceImage);
|
||||
if (destinationImage.Width != size.Width || destinationImage.Height != size.Height)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Destination image must have the size expected by the filter.");
|
||||
}
|
||||
ProcessFilter(sourceImage, destinationImage);
|
||||
}
|
||||
|
||||
protected abstract Size CalculateNewImageSize(UnmanagedImage sourceData);
|
||||
|
||||
protected abstract void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData);
|
||||
|
||||
private void CheckSourceFormat(PixelFormat pixelFormat)
|
||||
{
|
||||
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (!FormatTranslations.ContainsKey(pixelFormat))
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Source pixel format is not supported by the filter.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public abstract class BaseUsingCopyPartialFilter : IFilter, IInPlaceFilter, IInPlacePartialFilter, IFilterInformation
|
||||
{
|
||||
public abstract Dictionary<PixelFormat, PixelFormat> FormatTranslations { get; }
|
||||
|
||||
public Bitmap Apply(Bitmap image)
|
||||
{
|
||||
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)1, ((Image)image).PixelFormat);
|
||||
Bitmap val2 = null;
|
||||
try
|
||||
{
|
||||
val2 = Apply(val);
|
||||
if (((Image)image).HorizontalResolution > 0f && ((Image)image).VerticalResolution > 0f)
|
||||
{
|
||||
val2.SetResolution(((Image)image).HorizontalResolution, ((Image)image).VerticalResolution);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
}
|
||||
return val2;
|
||||
}
|
||||
|
||||
public Bitmap Apply(BitmapData imageData)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0032: Invalid comparison between Unknown and I4
|
||||
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(imageData.PixelFormat);
|
||||
int width = imageData.Width;
|
||||
int height = imageData.Height;
|
||||
PixelFormat val = FormatTranslations[imageData.PixelFormat];
|
||||
Bitmap val2 = (Bitmap)(((int)val == 198659) ? ((object)Image.CreateGrayscaleImage(width, height)) : ((object)new Bitmap(width, height, val)));
|
||||
BitmapData val3 = val2.LockBits(new Rectangle(0, 0, width, height), (ImageLockMode)3, val);
|
||||
try
|
||||
{
|
||||
ProcessFilter(new UnmanagedImage(imageData), new UnmanagedImage(val3), new Rectangle(0, 0, width, height));
|
||||
}
|
||||
finally
|
||||
{
|
||||
val2.UnlockBits(val3);
|
||||
}
|
||||
return val2;
|
||||
}
|
||||
|
||||
public UnmanagedImage Apply(UnmanagedImage image)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(image.PixelFormat);
|
||||
UnmanagedImage unmanagedImage = UnmanagedImage.Create(image.Width, image.Height, FormatTranslations[image.PixelFormat]);
|
||||
ProcessFilter(image, unmanagedImage, new Rectangle(0, 0, image.Width, image.Height));
|
||||
return unmanagedImage;
|
||||
}
|
||||
|
||||
public void Apply(UnmanagedImage sourceImage, UnmanagedImage destinationImage)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(sourceImage.PixelFormat);
|
||||
if (destinationImage.PixelFormat != FormatTranslations[sourceImage.PixelFormat])
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Destination pixel format is specified incorrectly.");
|
||||
}
|
||||
if (destinationImage.Width != sourceImage.Width || destinationImage.Height != sourceImage.Height)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Destination image must have the same width and height as source image.");
|
||||
}
|
||||
ProcessFilter(sourceImage, destinationImage, new Rectangle(0, 0, sourceImage.Width, sourceImage.Height));
|
||||
}
|
||||
|
||||
public void ApplyInPlace(Bitmap image)
|
||||
{
|
||||
ApplyInPlace(image, new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height));
|
||||
}
|
||||
|
||||
public void ApplyInPlace(BitmapData imageData)
|
||||
{
|
||||
ApplyInPlace(new UnmanagedImage(imageData), new Rectangle(0, 0, imageData.Width, imageData.Height));
|
||||
}
|
||||
|
||||
public void ApplyInPlace(UnmanagedImage image)
|
||||
{
|
||||
ApplyInPlace(image, new Rectangle(0, 0, image.Width, image.Height));
|
||||
}
|
||||
|
||||
public void ApplyInPlace(Bitmap image, Rectangle rect)
|
||||
{
|
||||
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)3, ((Image)image).PixelFormat);
|
||||
try
|
||||
{
|
||||
ApplyInPlace(new UnmanagedImage(val), rect);
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyInPlace(BitmapData imageData, Rectangle rect)
|
||||
{
|
||||
ApplyInPlace(new UnmanagedImage(imageData), rect);
|
||||
}
|
||||
|
||||
public void ApplyInPlace(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
|
||||
CheckSourceFormat(image.PixelFormat);
|
||||
rect.Intersect(new Rectangle(0, 0, image.Width, image.Height));
|
||||
if ((rect.Width | rect.Height) != 0)
|
||||
{
|
||||
int num = image.Stride * image.Height;
|
||||
IntPtr intPtr = MemoryManager.Alloc(num);
|
||||
SystemTools.CopyUnmanagedMemory(intPtr, image.ImageData, num);
|
||||
ProcessFilter(new UnmanagedImage(intPtr, image.Width, image.Height, image.Stride, image.PixelFormat), image, rect);
|
||||
MemoryManager.Free(intPtr);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect);
|
||||
|
||||
private void CheckSourceFormat(PixelFormat pixelFormat)
|
||||
{
|
||||
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (!FormatTranslations.ContainsKey(pixelFormat))
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Source pixel format is not supported by the filter.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public sealed class BayerDithering : OrderedDithering
|
||||
{
|
||||
public BayerDithering()
|
||||
: base(new byte[4, 4]
|
||||
{
|
||||
{ 0, 192, 48, 240 },
|
||||
{ 128, 64, 176, 112 },
|
||||
{ 32, 224, 16, 208 },
|
||||
{ 160, 96, 144, 80 }
|
||||
})
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class BayerFilter : BaseFilter
|
||||
{
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
private bool performDemosaicing = true;
|
||||
|
||||
private int[,] bayerPattern = new int[2, 2]
|
||||
{
|
||||
{ 1, 2 },
|
||||
{ 0, 1 }
|
||||
};
|
||||
|
||||
public bool PerformDemosaicing
|
||||
{
|
||||
get
|
||||
{
|
||||
return performDemosaicing;
|
||||
}
|
||||
set
|
||||
{
|
||||
performDemosaicing = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int[,] BayerPattern
|
||||
{
|
||||
get
|
||||
{
|
||||
return bayerPattern;
|
||||
}
|
||||
set
|
||||
{
|
||||
bayerPattern = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public BayerFilter()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)137224;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
|
||||
{
|
||||
int width = sourceData.Width;
|
||||
int height = sourceData.Height;
|
||||
int num = width - 1;
|
||||
int num2 = height - 1;
|
||||
int stride = sourceData.Stride;
|
||||
int num3 = stride - width;
|
||||
int num4 = destinationData.Stride - width * 3;
|
||||
byte* ptr = (byte*)sourceData.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destinationData.ImageData.ToPointer();
|
||||
int[] array = new int[3];
|
||||
int[] array2 = new int[3];
|
||||
if (!performDemosaicing)
|
||||
{
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
int num5 = 0;
|
||||
while (num5 < width)
|
||||
{
|
||||
ptr2[2] = (ptr2[1] = (*ptr2 = 0));
|
||||
ptr2[bayerPattern[i & 1, num5 & 1]] = *ptr;
|
||||
num5++;
|
||||
ptr++;
|
||||
ptr2 += 3;
|
||||
}
|
||||
ptr += num3;
|
||||
ptr2 += num4;
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
int num6 = 0;
|
||||
while (num6 < width)
|
||||
{
|
||||
array[0] = (array[1] = (array[2] = 0));
|
||||
array2[0] = (array2[1] = (array2[2] = 0));
|
||||
int num7 = bayerPattern[j & 1, num6 & 1];
|
||||
array[num7] += *ptr;
|
||||
array2[num7]++;
|
||||
if (num6 != 0)
|
||||
{
|
||||
num7 = bayerPattern[j & 1, (num6 - 1) & 1];
|
||||
array[num7] += ptr[-1];
|
||||
array2[num7]++;
|
||||
}
|
||||
if (num6 != num)
|
||||
{
|
||||
num7 = bayerPattern[j & 1, (num6 + 1) & 1];
|
||||
array[num7] += ptr[1];
|
||||
array2[num7]++;
|
||||
}
|
||||
if (j != 0)
|
||||
{
|
||||
num7 = bayerPattern[(j - 1) & 1, num6 & 1];
|
||||
array[num7] += ptr[-stride];
|
||||
array2[num7]++;
|
||||
if (num6 != 0)
|
||||
{
|
||||
num7 = bayerPattern[(j - 1) & 1, (num6 - 1) & 1];
|
||||
array[num7] += ptr[-stride - 1];
|
||||
array2[num7]++;
|
||||
}
|
||||
if (num6 != num)
|
||||
{
|
||||
num7 = bayerPattern[(j - 1) & 1, (num6 + 1) & 1];
|
||||
array[num7] += ptr[-stride + 1];
|
||||
array2[num7]++;
|
||||
}
|
||||
}
|
||||
if (j != num2)
|
||||
{
|
||||
num7 = bayerPattern[(j + 1) & 1, num6 & 1];
|
||||
array[num7] += ptr[stride];
|
||||
array2[num7]++;
|
||||
if (num6 != 0)
|
||||
{
|
||||
num7 = bayerPattern[(j + 1) & 1, (num6 - 1) & 1];
|
||||
array[num7] += ptr[stride - 1];
|
||||
array2[num7]++;
|
||||
}
|
||||
if (num6 != num)
|
||||
{
|
||||
num7 = bayerPattern[(j + 1) & 1, (num6 + 1) & 1];
|
||||
array[num7] += ptr[stride + 1];
|
||||
array2[num7]++;
|
||||
}
|
||||
}
|
||||
ptr2[2] = (byte)(array[2] / array2[2]);
|
||||
ptr2[1] = (byte)(array[1] / array2[1]);
|
||||
*ptr2 = (byte)(array[0] / array2[0]);
|
||||
num6++;
|
||||
ptr++;
|
||||
ptr2 += 3;
|
||||
}
|
||||
ptr += num3;
|
||||
ptr2 += num4;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class BayerFilterOptimized : BaseFilter
|
||||
{
|
||||
private BayerPattern bayerPattern;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public BayerPattern Pattern
|
||||
{
|
||||
get
|
||||
{
|
||||
return bayerPattern;
|
||||
}
|
||||
set
|
||||
{
|
||||
bayerPattern = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public BayerFilterOptimized()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)137224;
|
||||
}
|
||||
|
||||
protected override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
|
||||
{
|
||||
int width = sourceData.Width;
|
||||
int height = sourceData.Height;
|
||||
if ((width & 1) == 1 || (height & 1) == 1 || width < 2 || height < 2)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Source image must have even width and height. Width and height can not be smaller than 2.");
|
||||
}
|
||||
switch (bayerPattern)
|
||||
{
|
||||
case BayerPattern.GRBG:
|
||||
ApplyGRBG(sourceData, destinationData);
|
||||
break;
|
||||
case BayerPattern.BGGR:
|
||||
ApplyBGGR(sourceData, destinationData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void ApplyGRBG(UnmanagedImage sourceData, UnmanagedImage destinationData)
|
||||
{
|
||||
int width = sourceData.Width;
|
||||
int height = sourceData.Height;
|
||||
int num = width - 1;
|
||||
int num2 = height - 1;
|
||||
int stride = sourceData.Stride;
|
||||
int stride2 = destinationData.Stride;
|
||||
int num3 = stride + 1;
|
||||
int num4 = stride - 1;
|
||||
int num5 = -stride;
|
||||
int num6 = num5 + 1;
|
||||
int num7 = num5 - 1;
|
||||
int num8 = stride - width;
|
||||
int num9 = stride2 - width * 3;
|
||||
byte* ptr = (byte*)sourceData.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destinationData.ImageData.ToPointer();
|
||||
ptr2[2] = ptr[1];
|
||||
ptr2[1] = (byte)(*ptr + ptr[num3] >> 1);
|
||||
*ptr2 = ptr[stride];
|
||||
ptr++;
|
||||
ptr2 += 3;
|
||||
for (int i = 1; i < num; i += 2)
|
||||
{
|
||||
ptr2[2] = *ptr;
|
||||
ptr2[1] = (byte)((ptr[stride] + ptr[-1] + ptr[1]) / 3);
|
||||
*ptr2 = (byte)(ptr[num4] + ptr[num3] >> 1);
|
||||
ptr++;
|
||||
ptr2 += 3;
|
||||
ptr2[2] = (byte)(ptr[-1] + ptr[1] >> 1);
|
||||
ptr2[1] = (byte)((*ptr + ptr[num4] + ptr[num3]) / 3);
|
||||
*ptr2 = ptr[stride];
|
||||
ptr++;
|
||||
ptr2 += 3;
|
||||
}
|
||||
ptr2[2] = *ptr;
|
||||
ptr2[1] = (byte)(ptr[-1] + ptr[stride] >> 1);
|
||||
*ptr2 = ptr[num4];
|
||||
ptr += num8 + 1;
|
||||
ptr2 += num9 + 3;
|
||||
for (int j = 1; j < num2; j += 2)
|
||||
{
|
||||
ptr2[2] = (byte)(ptr[num6] + ptr[num3] >> 1);
|
||||
ptr2[1] = (byte)((ptr[num5] + ptr[stride] + ptr[1]) / 3);
|
||||
*ptr2 = *ptr;
|
||||
ptr2 += stride2;
|
||||
ptr += stride;
|
||||
ptr2[2] = ptr[1];
|
||||
ptr2[1] = (byte)((*ptr + ptr[num6] + ptr[num3]) / 3);
|
||||
*ptr2 = (byte)(ptr[num5] + ptr[stride] >> 1);
|
||||
ptr2 -= stride2;
|
||||
ptr -= stride;
|
||||
ptr++;
|
||||
ptr2 += 3;
|
||||
for (int k = 1; k < num; k += 2)
|
||||
{
|
||||
ptr2[2] = (byte)(ptr[num5] + ptr[stride] >> 1);
|
||||
ptr2[1] = (byte)((*ptr + ptr[num7] + ptr[num6] + ptr[num4] + ptr[num3]) / 5);
|
||||
*ptr2 = (byte)(ptr[-1] + ptr[1] >> 1);
|
||||
ptr2 += stride2;
|
||||
ptr += stride;
|
||||
ptr2[2] = *ptr;
|
||||
ptr2[1] = (byte)(ptr[num5] + ptr[stride] + ptr[-1] + ptr[1] >> 2);
|
||||
*ptr2 = (byte)(ptr[num7] + ptr[num6] + ptr[num4] + ptr[num3] >> 2);
|
||||
ptr2 += 3;
|
||||
ptr++;
|
||||
ptr2[2] = (byte)(ptr[-1] + ptr[1] >> 1);
|
||||
ptr2[1] = (byte)((*ptr + ptr[num7] + ptr[num6] + ptr[num4] + ptr[num3]) / 5);
|
||||
*ptr2 = (byte)(ptr[num5] + ptr[stride] >> 1);
|
||||
ptr2 -= stride2;
|
||||
ptr -= stride;
|
||||
ptr2[2] = (byte)(ptr[num7] + ptr[num6] + ptr[num4] + ptr[num3] >> 2);
|
||||
ptr2[1] = (byte)(ptr[num5] + ptr[stride] + ptr[-1] + ptr[1] >> 2);
|
||||
*ptr2 = *ptr;
|
||||
ptr2 += 3;
|
||||
ptr++;
|
||||
}
|
||||
ptr2[2] = (byte)(ptr[num5] + ptr[stride] >> 1);
|
||||
ptr2[1] = (byte)((*ptr + ptr[num7] + ptr[num4]) / 3);
|
||||
*ptr2 = ptr[-1];
|
||||
ptr += stride;
|
||||
ptr2 += stride2;
|
||||
ptr2[2] = *ptr;
|
||||
ptr2[1] = (byte)((ptr[num5] + ptr[stride] + ptr[-1]) / 3);
|
||||
*ptr2 = (byte)(ptr[num7] + ptr[num4] >> 1);
|
||||
ptr += num8 + 1;
|
||||
ptr2 += num9 + 3;
|
||||
}
|
||||
ptr2[2] = ptr[num6];
|
||||
ptr2[1] = (byte)(ptr[num5] + ptr[1] >> 1);
|
||||
*ptr2 = *ptr;
|
||||
ptr++;
|
||||
ptr2 += 3;
|
||||
for (int l = 1; l < num; l += 2)
|
||||
{
|
||||
ptr2[2] = ptr[num5];
|
||||
ptr2[1] = (byte)((ptr[num7] + ptr[num6] + *ptr) / 3);
|
||||
*ptr2 = (byte)(ptr[-1] + ptr[1] >> 1);
|
||||
ptr++;
|
||||
ptr2 += 3;
|
||||
ptr2[2] = (byte)(ptr[num7] + ptr[num6] >> 1);
|
||||
ptr2[1] = (byte)((ptr[num5] + ptr[-1] + ptr[1]) / 3);
|
||||
*ptr2 = *ptr;
|
||||
ptr++;
|
||||
ptr2 += 3;
|
||||
}
|
||||
ptr2[2] = ptr[num5];
|
||||
ptr2[1] = (byte)(*ptr + ptr[num7] >> 1);
|
||||
*ptr2 = ptr[-1];
|
||||
}
|
||||
|
||||
private unsafe void ApplyBGGR(UnmanagedImage sourceData, UnmanagedImage destinationData)
|
||||
{
|
||||
int width = sourceData.Width;
|
||||
int height = sourceData.Height;
|
||||
int num = width - 1;
|
||||
int num2 = height - 1;
|
||||
int stride = sourceData.Stride;
|
||||
int stride2 = destinationData.Stride;
|
||||
int num3 = stride + 1;
|
||||
int num4 = stride - 1;
|
||||
int num5 = -stride;
|
||||
int num6 = num5 + 1;
|
||||
int num7 = num5 - 1;
|
||||
int num8 = stride - width;
|
||||
int num9 = stride2 - width * 3;
|
||||
byte* ptr = (byte*)sourceData.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destinationData.ImageData.ToPointer();
|
||||
ptr2[2] = ptr[num3];
|
||||
ptr2[1] = (byte)(ptr[1] + ptr[stride] >> 1);
|
||||
*ptr2 = *ptr;
|
||||
ptr++;
|
||||
ptr2 += 3;
|
||||
for (int i = 1; i < num; i += 2)
|
||||
{
|
||||
ptr2[2] = ptr[stride];
|
||||
ptr2[1] = (byte)((*ptr + ptr[num4] + ptr[num3]) / 3);
|
||||
*ptr2 = (byte)(ptr[-1] + ptr[1] >> 1);
|
||||
ptr++;
|
||||
ptr2 += 3;
|
||||
ptr2[2] = (byte)(ptr[num4] + ptr[num3] >> 1);
|
||||
ptr2[1] = (byte)((ptr[-1] + ptr[stride] + ptr[1]) / 3);
|
||||
*ptr2 = *ptr;
|
||||
ptr++;
|
||||
ptr2 += 3;
|
||||
}
|
||||
ptr2[2] = ptr[stride];
|
||||
ptr2[1] = (byte)(*ptr + ptr[num4] >> 1);
|
||||
*ptr2 = ptr[-1];
|
||||
ptr += num8 + 1;
|
||||
ptr2 += num9 + 3;
|
||||
for (int j = 1; j < num2; j += 2)
|
||||
{
|
||||
ptr2[2] = ptr[1];
|
||||
ptr2[1] = (byte)((ptr[num6] + ptr[num3] + *ptr) / 3);
|
||||
*ptr2 = (byte)(ptr[num5] + ptr[stride] >> 1);
|
||||
ptr2 += stride2;
|
||||
ptr += stride;
|
||||
ptr2[2] = (byte)(ptr[num6] + ptr[num3] >> 1);
|
||||
ptr2[1] = (byte)((ptr[1] + ptr[num5] + ptr[stride]) / 3);
|
||||
*ptr2 = *ptr;
|
||||
ptr2 -= stride2;
|
||||
ptr -= stride;
|
||||
ptr++;
|
||||
ptr2 += 3;
|
||||
for (int k = 1; k < num; k += 2)
|
||||
{
|
||||
ptr2[2] = *ptr;
|
||||
ptr2[1] = (byte)(ptr[num5] + ptr[stride] + ptr[-1] + ptr[1] >> 2);
|
||||
*ptr2 = (byte)(ptr[num7] + ptr[num6] + ptr[num4] + ptr[num3] >> 2);
|
||||
ptr2 += stride2;
|
||||
ptr += stride;
|
||||
ptr2[2] = (byte)(ptr[num5] + ptr[stride] >> 1);
|
||||
ptr2[1] = (byte)((*ptr + ptr[num7] + ptr[num6] + ptr[num4] + ptr[num3]) / 5);
|
||||
*ptr2 = (byte)(ptr[-1] + ptr[1] >> 1);
|
||||
ptr2 += 3;
|
||||
ptr++;
|
||||
ptr2[2] = (byte)(ptr[num7] + ptr[num6] + ptr[num4] + ptr[num3] >> 2);
|
||||
ptr2[1] = (byte)(ptr[num5] + ptr[stride] + ptr[-1] + ptr[1] >> 2);
|
||||
*ptr2 = *ptr;
|
||||
ptr2 -= stride2;
|
||||
ptr -= stride;
|
||||
ptr2[2] = (byte)(ptr[-1] + ptr[1] >> 1);
|
||||
ptr2[1] = (byte)((ptr[num7] + ptr[num6] + ptr[num4] + ptr[num3] + *ptr) / 5);
|
||||
*ptr2 = (byte)(ptr[num5] + ptr[stride] >> 1);
|
||||
ptr2 += 3;
|
||||
ptr++;
|
||||
}
|
||||
ptr2[2] = *ptr;
|
||||
ptr2[1] = (byte)((ptr[num5] + ptr[stride] + ptr[-1]) / 3);
|
||||
*ptr2 = (byte)(ptr[num7] + ptr[num4] >> 1);
|
||||
ptr += stride;
|
||||
ptr2 += stride2;
|
||||
ptr2[2] = (byte)(ptr[num5] + ptr[stride] >> 1);
|
||||
ptr2[1] = (byte)((ptr[num7] + ptr[num4] + *ptr) / 3);
|
||||
*ptr2 = ptr[-1];
|
||||
ptr += num8 + 1;
|
||||
ptr2 += num9 + 3;
|
||||
}
|
||||
ptr2[2] = ptr[1];
|
||||
ptr2[1] = (byte)(ptr[num6] + *ptr >> 1);
|
||||
*ptr2 = ptr[num5];
|
||||
ptr++;
|
||||
ptr2 += 3;
|
||||
for (int l = 1; l < num; l += 2)
|
||||
{
|
||||
ptr2[2] = *ptr;
|
||||
ptr2[1] = (byte)((ptr[-1] + ptr[1] + ptr[num5]) / 3);
|
||||
*ptr2 = (byte)(ptr[num7] + ptr[num6] >> 1);
|
||||
ptr++;
|
||||
ptr2 += 3;
|
||||
ptr2[2] = (byte)(ptr[-1] + ptr[1] >> 1);
|
||||
ptr2[1] = (byte)((*ptr + ptr[num7] + ptr[num6]) / 3);
|
||||
*ptr2 = ptr[num5];
|
||||
ptr++;
|
||||
ptr2 += 3;
|
||||
}
|
||||
ptr2[2] = *ptr;
|
||||
ptr2[1] = (byte)(ptr[num5] + ptr[-1] >> 1);
|
||||
*ptr2 = ptr[num7];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public enum BayerPattern
|
||||
{
|
||||
GRBG,
|
||||
BGGR
|
||||
}
|
||||
@@ -0,0 +1,581 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class BilateralSmoothing : BaseUsingCopyPartialFilter
|
||||
{
|
||||
private const int maxKernelSize = 255;
|
||||
|
||||
private const int colorsCount = 256;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
private int kernelSize = 9;
|
||||
|
||||
private double spatialFactor = 10.0;
|
||||
|
||||
private double spatialPower = 2.0;
|
||||
|
||||
private double colorFactor = 50.0;
|
||||
|
||||
private double colorPower = 2.0;
|
||||
|
||||
private bool spatialPropertiesChanged = true;
|
||||
|
||||
private bool colorPropertiesChanged = true;
|
||||
|
||||
private bool limitKernelSize = true;
|
||||
|
||||
private bool enableParallelProcessing;
|
||||
|
||||
private double[,] spatialFunc;
|
||||
|
||||
private double[,] colorFunc;
|
||||
|
||||
public bool LimitKernelSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return limitKernelSize;
|
||||
}
|
||||
set
|
||||
{
|
||||
limitKernelSize = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool EnableParallelProcessing
|
||||
{
|
||||
get
|
||||
{
|
||||
return enableParallelProcessing;
|
||||
}
|
||||
set
|
||||
{
|
||||
enableParallelProcessing = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int KernelSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return kernelSize;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value > 255)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("Maximum allowed value of KernelSize property is " + 255);
|
||||
}
|
||||
if (limitKernelSize && value > 25)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("KernerlSize is larger then 25. Time for applying is significant and may lead to application freezing. In order to use any KernelSize value set property 'LimitKernelSize' to false.");
|
||||
}
|
||||
if (value < 3)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("KernelSize must be greater than 3");
|
||||
}
|
||||
if (value % 2 == 0)
|
||||
{
|
||||
throw new ArgumentException("KernerlSize must be an odd integer.");
|
||||
}
|
||||
kernelSize = value;
|
||||
}
|
||||
}
|
||||
|
||||
public double SpatialFactor
|
||||
{
|
||||
get
|
||||
{
|
||||
return spatialFactor;
|
||||
}
|
||||
set
|
||||
{
|
||||
spatialFactor = System.Math.Max(1.0, value);
|
||||
spatialPropertiesChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public double SpatialPower
|
||||
{
|
||||
get
|
||||
{
|
||||
return spatialPower;
|
||||
}
|
||||
set
|
||||
{
|
||||
spatialPower = System.Math.Max(1.0, value);
|
||||
spatialPropertiesChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public double ColorFactor
|
||||
{
|
||||
get
|
||||
{
|
||||
return colorFactor;
|
||||
}
|
||||
set
|
||||
{
|
||||
colorFactor = System.Math.Max(1.0, value);
|
||||
colorPropertiesChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public double ColorPower
|
||||
{
|
||||
get
|
||||
{
|
||||
return colorPower;
|
||||
}
|
||||
set
|
||||
{
|
||||
colorPower = System.Math.Max(1.0, value);
|
||||
colorPropertiesChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public BilateralSmoothing()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
}
|
||||
|
||||
private void InitSpatialFunc()
|
||||
{
|
||||
if (spatialFunc != null && spatialFunc.Length == kernelSize * kernelSize && !spatialPropertiesChanged)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (spatialFunc == null || spatialFunc.Length != kernelSize * kernelSize)
|
||||
{
|
||||
spatialFunc = new double[kernelSize, kernelSize];
|
||||
}
|
||||
int num = kernelSize / 2;
|
||||
for (int i = 0; i < kernelSize; i++)
|
||||
{
|
||||
int num2 = i - num;
|
||||
int num3 = num2 * num2;
|
||||
for (int j = 0; j < kernelSize; j++)
|
||||
{
|
||||
int num4 = j - num;
|
||||
int num5 = num4 * num4;
|
||||
spatialFunc[i, j] = System.Math.Exp(-0.5 * System.Math.Pow(System.Math.Sqrt((double)(num3 + num5) / spatialFactor), spatialPower));
|
||||
}
|
||||
}
|
||||
spatialPropertiesChanged = false;
|
||||
}
|
||||
|
||||
private void InitColorFunc()
|
||||
{
|
||||
if (colorFunc != null && !colorPropertiesChanged)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (colorFunc == null)
|
||||
{
|
||||
colorFunc = new double[256, 256];
|
||||
}
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
for (int j = 0; j < 256; j++)
|
||||
{
|
||||
colorFunc[i, j] = System.Math.Exp(-0.5 * System.Math.Pow((double)System.Math.Abs(i - j) / colorFactor, colorPower));
|
||||
}
|
||||
}
|
||||
colorPropertiesChanged = false;
|
||||
}
|
||||
|
||||
private void InitFilter()
|
||||
{
|
||||
InitSpatialFunc();
|
||||
InitColorFunc();
|
||||
}
|
||||
|
||||
protected override void ProcessFilter(UnmanagedImage source, UnmanagedImage destination, Rectangle rect)
|
||||
{
|
||||
int num = kernelSize / 2;
|
||||
InitFilter();
|
||||
if (rect.Width <= kernelSize || rect.Height <= kernelSize)
|
||||
{
|
||||
ProcessWithEdgeChecks(source, destination, rect);
|
||||
return;
|
||||
}
|
||||
Rectangle rect2 = rect;
|
||||
rect2.Inflate(-num, -num);
|
||||
if (Environment.ProcessorCount > 1 && enableParallelProcessing)
|
||||
{
|
||||
ProcessWithoutChecksParallel(source, destination, rect2);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessWithoutChecks(source, destination, rect2);
|
||||
}
|
||||
ProcessWithEdgeChecks(source, destination, new Rectangle(rect.Left, rect.Top, rect.Width, num));
|
||||
ProcessWithEdgeChecks(source, destination, new Rectangle(rect.Left, rect.Bottom - num, rect.Width, num));
|
||||
ProcessWithEdgeChecks(source, destination, new Rectangle(rect.Left, rect.Top + num, num, rect.Height - num * 2));
|
||||
ProcessWithEdgeChecks(source, destination, new Rectangle(rect.Right - num, rect.Top + num, num, rect.Height - num * 2));
|
||||
}
|
||||
|
||||
private unsafe void ProcessWithoutChecksParallel(UnmanagedImage source, UnmanagedImage destination, Rectangle rect)
|
||||
{
|
||||
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
|
||||
int startX = rect.Left;
|
||||
int top = rect.Top;
|
||||
int stopX = rect.Right;
|
||||
int bottom = rect.Bottom;
|
||||
int pixelSize = Image.GetPixelFormatSize(source.PixelFormat) / 8;
|
||||
int num = kernelSize / 2;
|
||||
int num2 = kernelSize * pixelSize;
|
||||
int srcStride = source.Stride;
|
||||
int dstStride = destination.Stride;
|
||||
_ = srcStride;
|
||||
_ = rect.Width;
|
||||
_ = pixelSize;
|
||||
_ = dstStride;
|
||||
_ = rect.Width;
|
||||
_ = pixelSize;
|
||||
int srcKernelFistPixelOffset = num * (srcStride + pixelSize);
|
||||
int srcKernelOffset = srcStride - num2;
|
||||
byte* srcBase = (byte*)source.ImageData.ToPointer();
|
||||
byte* dstBase = (byte*)destination.ImageData.ToPointer();
|
||||
srcBase += (nint)startX * (nint)pixelSize;
|
||||
dstBase += (nint)startX * (nint)pixelSize;
|
||||
if (pixelSize > 1)
|
||||
{
|
||||
Parallel.For(top, bottom, delegate(int y)
|
||||
{
|
||||
byte* ptr = srcBase + (nint)y * (nint)srcStride;
|
||||
byte* ptr2 = dstBase + (nint)y * (nint)dstStride;
|
||||
int num3 = startX;
|
||||
while (num3 < stopX)
|
||||
{
|
||||
byte* ptr3 = ptr + srcKernelFistPixelOffset;
|
||||
double num4 = 0.0;
|
||||
double num5 = 0.0;
|
||||
double num6 = 0.0;
|
||||
double num7 = 0.0;
|
||||
double num8 = 0.0;
|
||||
double num9 = 0.0;
|
||||
byte b = ptr[2];
|
||||
byte b2 = ptr[1];
|
||||
byte b3 = *ptr;
|
||||
int num10 = kernelSize;
|
||||
while (num10 != 0)
|
||||
{
|
||||
num10--;
|
||||
int num11 = kernelSize;
|
||||
while (num11 != 0)
|
||||
{
|
||||
num11--;
|
||||
byte b4 = ptr3[2];
|
||||
byte b5 = ptr3[1];
|
||||
byte b6 = *ptr3;
|
||||
double num12 = spatialFunc[num11, num10] * colorFunc[b4, b];
|
||||
double num13 = spatialFunc[num11, num10] * colorFunc[b5, b2];
|
||||
double num14 = spatialFunc[num11, num10] * colorFunc[b6, b3];
|
||||
num4 += num12;
|
||||
num5 += num13;
|
||||
num6 += num14;
|
||||
num7 += num12 * (double)(int)b4;
|
||||
num8 += num13 * (double)(int)b5;
|
||||
num9 += num14 * (double)(int)b6;
|
||||
ptr3 -= pixelSize;
|
||||
}
|
||||
ptr3 -= srcKernelOffset;
|
||||
}
|
||||
ptr2[2] = (byte)(num7 / num4);
|
||||
ptr2[1] = (byte)(num8 / num5);
|
||||
*ptr2 = (byte)(num9 / num6);
|
||||
num3++;
|
||||
ptr += pixelSize;
|
||||
ptr2 += pixelSize;
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
Parallel.For(top, bottom, delegate(int y)
|
||||
{
|
||||
byte* ptr = srcBase + (nint)y * (nint)srcStride;
|
||||
byte* ptr2 = dstBase + (nint)y * (nint)dstStride;
|
||||
int num3 = startX;
|
||||
while (num3 < stopX)
|
||||
{
|
||||
byte* ptr3 = ptr + srcKernelFistPixelOffset;
|
||||
double num4 = 0.0;
|
||||
double num5 = 0.0;
|
||||
byte b = *ptr;
|
||||
int num6 = kernelSize;
|
||||
while (num6 != 0)
|
||||
{
|
||||
num6--;
|
||||
int num7 = kernelSize;
|
||||
while (num7 != 0)
|
||||
{
|
||||
num7--;
|
||||
byte b2 = *ptr3;
|
||||
double num8 = spatialFunc[num7, num6] * colorFunc[b2, b];
|
||||
num4 += num8;
|
||||
num5 += num8 * (double)(int)b2;
|
||||
ptr3 -= pixelSize;
|
||||
}
|
||||
ptr3 -= srcKernelOffset;
|
||||
}
|
||||
*ptr2 = (byte)(num5 / num4);
|
||||
num3++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private unsafe void ProcessWithoutChecks(UnmanagedImage source, UnmanagedImage destination, Rectangle rect)
|
||||
{
|
||||
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
|
||||
int left = rect.Left;
|
||||
int top = rect.Top;
|
||||
int right = rect.Right;
|
||||
int bottom = rect.Bottom;
|
||||
int num = Image.GetPixelFormatSize(source.PixelFormat) / 8;
|
||||
int num2 = kernelSize / 2;
|
||||
int num3 = kernelSize * num;
|
||||
int stride = source.Stride;
|
||||
int stride2 = destination.Stride;
|
||||
int num4 = stride - rect.Width * num;
|
||||
int num5 = stride2 - rect.Width * num;
|
||||
int num6 = num2 * (stride + num);
|
||||
int num7 = stride - num3;
|
||||
byte* ptr = (byte*)source.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destination.ImageData.ToPointer();
|
||||
ptr += top * stride + left * num;
|
||||
ptr2 += top * stride2 + left * num;
|
||||
if (num > 1)
|
||||
{
|
||||
for (int i = top; i < bottom; i++)
|
||||
{
|
||||
int num8 = left;
|
||||
while (num8 < right)
|
||||
{
|
||||
byte* ptr3 = ptr + num6;
|
||||
double num9 = 0.0;
|
||||
double num10 = 0.0;
|
||||
double num11 = 0.0;
|
||||
double num12 = 0.0;
|
||||
double num13 = 0.0;
|
||||
double num14 = 0.0;
|
||||
byte b = ptr[2];
|
||||
byte b2 = ptr[1];
|
||||
byte b3 = *ptr;
|
||||
int num15 = kernelSize;
|
||||
while (num15 != 0)
|
||||
{
|
||||
num15--;
|
||||
int num16 = kernelSize;
|
||||
while (num16 != 0)
|
||||
{
|
||||
num16--;
|
||||
byte b4 = ptr3[2];
|
||||
byte b5 = ptr3[1];
|
||||
byte b6 = *ptr3;
|
||||
double num17 = spatialFunc[num16, num15] * colorFunc[b4, b];
|
||||
double num18 = spatialFunc[num16, num15] * colorFunc[b5, b2];
|
||||
double num19 = spatialFunc[num16, num15] * colorFunc[b6, b3];
|
||||
num9 += num17;
|
||||
num10 += num18;
|
||||
num11 += num19;
|
||||
num12 += num17 * (double)(int)b4;
|
||||
num13 += num18 * (double)(int)b5;
|
||||
num14 += num19 * (double)(int)b6;
|
||||
ptr3 -= num;
|
||||
}
|
||||
ptr3 -= num7;
|
||||
}
|
||||
ptr2[2] = (byte)(num12 / num9);
|
||||
ptr2[1] = (byte)(num13 / num10);
|
||||
*ptr2 = (byte)(num14 / num11);
|
||||
num8++;
|
||||
ptr += num;
|
||||
ptr2 += num;
|
||||
}
|
||||
ptr += num4;
|
||||
ptr2 += num5;
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int j = top; j < bottom; j++)
|
||||
{
|
||||
int num20 = left;
|
||||
while (num20 < right)
|
||||
{
|
||||
byte* ptr4 = ptr + num6;
|
||||
double num21 = 0.0;
|
||||
double num22 = 0.0;
|
||||
byte b7 = *ptr;
|
||||
int num15 = kernelSize;
|
||||
while (num15 != 0)
|
||||
{
|
||||
num15--;
|
||||
int num16 = kernelSize;
|
||||
while (num16 != 0)
|
||||
{
|
||||
num16--;
|
||||
byte b8 = *ptr4;
|
||||
double num23 = spatialFunc[num16, num15] * colorFunc[b8, b7];
|
||||
num21 += num23;
|
||||
num22 += num23 * (double)(int)b8;
|
||||
ptr4 -= num;
|
||||
}
|
||||
ptr4 -= num7;
|
||||
}
|
||||
*ptr2 = (byte)(num22 / num21);
|
||||
num20++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
ptr += num4;
|
||||
ptr2 += num5;
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void ProcessWithEdgeChecks(UnmanagedImage source, UnmanagedImage destination, Rectangle rect)
|
||||
{
|
||||
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
|
||||
int width = source.Width;
|
||||
int height = source.Height;
|
||||
int left = rect.Left;
|
||||
int top = rect.Top;
|
||||
int right = rect.Right;
|
||||
int bottom = rect.Bottom;
|
||||
int num = Image.GetPixelFormatSize(source.PixelFormat) / 8;
|
||||
int num2 = kernelSize / 2;
|
||||
int num3 = kernelSize * num;
|
||||
int stride = source.Stride;
|
||||
int stride2 = destination.Stride;
|
||||
int num4 = stride - rect.Width * num;
|
||||
int num5 = stride2 - rect.Width * num;
|
||||
int num6 = num2 * (stride + num);
|
||||
int num7 = stride - num3;
|
||||
byte* ptr = (byte*)source.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destination.ImageData.ToPointer();
|
||||
ptr += top * stride + left * num;
|
||||
ptr2 += top * stride2 + left * num;
|
||||
if (num > 1)
|
||||
{
|
||||
for (int i = top; i < bottom; i++)
|
||||
{
|
||||
int num8 = left;
|
||||
while (num8 < right)
|
||||
{
|
||||
byte* ptr3 = ptr + num6;
|
||||
double num9 = 0.0;
|
||||
double num10 = 0.0;
|
||||
double num11 = 0.0;
|
||||
double num12 = 0.0;
|
||||
double num13 = 0.0;
|
||||
double num14 = 0.0;
|
||||
byte b = ptr[2];
|
||||
byte b2 = ptr[1];
|
||||
byte b3 = *ptr;
|
||||
int num15 = kernelSize;
|
||||
while (num15 != 0)
|
||||
{
|
||||
num15--;
|
||||
int num16 = num15 - num2;
|
||||
if (num16 + i >= height || num16 + i < 0)
|
||||
{
|
||||
ptr3 -= stride;
|
||||
continue;
|
||||
}
|
||||
int num17 = kernelSize;
|
||||
while (num17 != 0)
|
||||
{
|
||||
num17--;
|
||||
int num18 = num17 - num2;
|
||||
if (num18 + num8 >= width || num18 + num8 < 0)
|
||||
{
|
||||
ptr3 -= num;
|
||||
continue;
|
||||
}
|
||||
byte b4 = ptr3[2];
|
||||
byte b5 = ptr3[1];
|
||||
byte b6 = *ptr3;
|
||||
double num19 = spatialFunc[num17, num15] * colorFunc[b4, b];
|
||||
double num20 = spatialFunc[num17, num15] * colorFunc[b5, b2];
|
||||
double num21 = spatialFunc[num17, num15] * colorFunc[b6, b3];
|
||||
num9 += num19;
|
||||
num10 += num20;
|
||||
num11 += num21;
|
||||
num12 += num19 * (double)(int)b4;
|
||||
num13 += num20 * (double)(int)b5;
|
||||
num14 += num21 * (double)(int)b6;
|
||||
ptr3 -= num;
|
||||
}
|
||||
ptr3 -= num7;
|
||||
}
|
||||
ptr2[2] = (byte)(num12 / num9);
|
||||
ptr2[1] = (byte)(num13 / num10);
|
||||
*ptr2 = (byte)(num14 / num11);
|
||||
num8++;
|
||||
ptr += num;
|
||||
ptr2 += num;
|
||||
}
|
||||
ptr += num4;
|
||||
ptr2 += num5;
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int j = top; j < bottom; j++)
|
||||
{
|
||||
int num22 = left;
|
||||
while (num22 < right)
|
||||
{
|
||||
byte* ptr4 = ptr + num6;
|
||||
double num23 = 0.0;
|
||||
double num24 = 0.0;
|
||||
byte b7 = *ptr;
|
||||
int num15 = kernelSize;
|
||||
while (num15 != 0)
|
||||
{
|
||||
num15--;
|
||||
int num16 = num15 - num2;
|
||||
if (num16 + j >= height || num16 + j < 0)
|
||||
{
|
||||
ptr4 -= stride;
|
||||
continue;
|
||||
}
|
||||
int num17 = kernelSize;
|
||||
while (num17 != 0)
|
||||
{
|
||||
num17--;
|
||||
int num18 = num17 - num2;
|
||||
if (num18 + num22 >= source.Width || num18 + num22 < 0)
|
||||
{
|
||||
ptr4 -= num;
|
||||
continue;
|
||||
}
|
||||
byte b8 = *ptr4;
|
||||
double num25 = spatialFunc[num17, num15] * colorFunc[b8, b7];
|
||||
num23 += num25;
|
||||
num24 += num25 * (double)(int)b8;
|
||||
ptr4 -= num;
|
||||
}
|
||||
ptr4 -= num7;
|
||||
}
|
||||
*ptr2 = (byte)(num24 / num23);
|
||||
num22++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
ptr += num4;
|
||||
ptr2 += num5;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class BinaryDilatation3x3 : BaseUsingCopyPartialFilter
|
||||
{
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public BinaryDilatation3x3()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect)
|
||||
{
|
||||
if (rect.Width < 3 || rect.Height < 3)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Processing rectangle mast be at least 3x3 in size.");
|
||||
}
|
||||
int num = rect.Left + 1;
|
||||
int num2 = rect.Top + 1;
|
||||
int num3 = rect.Right - 1;
|
||||
int num4 = rect.Bottom - 1;
|
||||
int stride = destinationData.Stride;
|
||||
int stride2 = sourceData.Stride;
|
||||
int num5 = stride - rect.Width + 1;
|
||||
int num6 = stride2 - rect.Width + 1;
|
||||
byte* ptr = (byte*)sourceData.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destinationData.ImageData.ToPointer();
|
||||
ptr += num - 1 + (num2 - 1) * stride2;
|
||||
ptr2 += num - 1 + (num2 - 1) * stride;
|
||||
*ptr2 = (byte)(*ptr | ptr[1] | ptr[stride2] | ptr[stride2 + 1]);
|
||||
ptr++;
|
||||
ptr2++;
|
||||
int num7 = num;
|
||||
while (num7 < num3)
|
||||
{
|
||||
*ptr2 = (byte)(*ptr | ptr[-1] | ptr[1] | ptr[stride2] | ptr[stride2 - 1] | ptr[stride2 + 1]);
|
||||
num7++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
*ptr2 = (byte)(*ptr | ptr[-1] | ptr[stride2] | ptr[stride2 - 1]);
|
||||
ptr += num6;
|
||||
ptr2 += num5;
|
||||
for (int i = num2; i < num4; i++)
|
||||
{
|
||||
*ptr2 = (byte)(*ptr | ptr[1] | ptr[-stride2] | ptr[-stride2 + 1] | ptr[stride2] | ptr[stride2 + 1]);
|
||||
ptr++;
|
||||
ptr2++;
|
||||
int num8 = num;
|
||||
while (num8 < num3)
|
||||
{
|
||||
*ptr2 = (byte)(*ptr | ptr[-1] | ptr[1] | ptr[-stride2] | ptr[-stride2 - 1] | ptr[-stride2 + 1] | ptr[stride2] | ptr[stride2 - 1] | ptr[stride2 + 1]);
|
||||
num8++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
*ptr2 = (byte)(*ptr | ptr[-1] | ptr[-stride2] | ptr[-stride2 - 1] | ptr[stride2] | ptr[stride2 - 1]);
|
||||
ptr += num6;
|
||||
ptr2 += num5;
|
||||
}
|
||||
*ptr2 = (byte)(*ptr | ptr[1] | ptr[-stride2] | ptr[-stride2 + 1]);
|
||||
ptr++;
|
||||
ptr2++;
|
||||
int num9 = num;
|
||||
while (num9 < num3)
|
||||
{
|
||||
*ptr2 = (byte)(*ptr | ptr[-1] | ptr[1] | ptr[-stride2] | ptr[-stride2 - 1] | ptr[-stride2 + 1]);
|
||||
num9++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
*ptr2 = (byte)(*ptr | ptr[-1] | ptr[-stride2] | ptr[-stride2 - 1]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class BinaryErosion3x3 : BaseUsingCopyPartialFilter
|
||||
{
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public BinaryErosion3x3()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect)
|
||||
{
|
||||
if (rect.Width < 3 || rect.Height < 3)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Processing rectangle mast be at least 3x3 in size.");
|
||||
}
|
||||
int num = rect.Left + 1;
|
||||
int num2 = rect.Top + 1;
|
||||
int num3 = rect.Right - 1;
|
||||
int num4 = rect.Bottom - 1;
|
||||
int stride = destinationData.Stride;
|
||||
int stride2 = sourceData.Stride;
|
||||
int num5 = stride - rect.Width + 1;
|
||||
int num6 = stride2 - rect.Width + 1;
|
||||
byte* ptr = (byte*)sourceData.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destinationData.ImageData.ToPointer();
|
||||
ptr += num - 1 + (num2 - 1) * stride2;
|
||||
ptr2 += num - 1 + (num2 - 1) * stride;
|
||||
int num7 = num - 1;
|
||||
while (num7 < num3)
|
||||
{
|
||||
*ptr2 = 0;
|
||||
num7++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
*ptr2 = 0;
|
||||
ptr += num6;
|
||||
ptr2 += num5;
|
||||
for (int i = num2; i < num4; i++)
|
||||
{
|
||||
*ptr2 = 0;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
int num8 = num;
|
||||
while (num8 < num3)
|
||||
{
|
||||
*ptr2 = (byte)(*ptr & ptr[-1] & ptr[1] & ptr[-stride2] & ptr[-stride2 - 1] & ptr[-stride2 + 1] & ptr[stride2] & ptr[stride2 - 1] & ptr[stride2 + 1]);
|
||||
num8++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
*ptr2 = 0;
|
||||
ptr += num6;
|
||||
ptr2 += num5;
|
||||
}
|
||||
int num9 = num - 1;
|
||||
while (num9 < num3)
|
||||
{
|
||||
*ptr2 = 0;
|
||||
num9++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
*ptr2 = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class BlobsFiltering : BaseInPlaceFilter
|
||||
{
|
||||
private BlobCounter blobCounter = new BlobCounter();
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public bool CoupledSizeFiltering
|
||||
{
|
||||
get
|
||||
{
|
||||
return blobCounter.CoupledSizeFiltering;
|
||||
}
|
||||
set
|
||||
{
|
||||
blobCounter.CoupledSizeFiltering = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int MinWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return blobCounter.MinWidth;
|
||||
}
|
||||
set
|
||||
{
|
||||
blobCounter.MinWidth = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int MinHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
return blobCounter.MinHeight;
|
||||
}
|
||||
set
|
||||
{
|
||||
blobCounter.MinHeight = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int MaxWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return blobCounter.MaxWidth;
|
||||
}
|
||||
set
|
||||
{
|
||||
blobCounter.MaxWidth = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int MaxHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
return blobCounter.MaxHeight;
|
||||
}
|
||||
set
|
||||
{
|
||||
blobCounter.MaxHeight = value;
|
||||
}
|
||||
}
|
||||
|
||||
public IBlobsFilter BlobsFilter
|
||||
{
|
||||
get
|
||||
{
|
||||
return blobCounter.BlobsFilter;
|
||||
}
|
||||
set
|
||||
{
|
||||
blobCounter.BlobsFilter = value;
|
||||
}
|
||||
}
|
||||
|
||||
public BlobsFiltering()
|
||||
{
|
||||
blobCounter.FilterBlobs = true;
|
||||
blobCounter.MinWidth = 1;
|
||||
blobCounter.MinHeight = 1;
|
||||
blobCounter.MaxWidth = int.MaxValue;
|
||||
blobCounter.MaxHeight = int.MaxValue;
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
formatTranslations[(PixelFormat)925707] = (PixelFormat)925707;
|
||||
}
|
||||
|
||||
public BlobsFiltering(int minWidth, int minHeight, int maxWidth, int maxHeight)
|
||||
: this(minWidth, minHeight, maxWidth, maxHeight, coupledSizeFiltering: false)
|
||||
{
|
||||
}
|
||||
|
||||
public BlobsFiltering(int minWidth, int minHeight, int maxWidth, int maxHeight, bool coupledSizeFiltering)
|
||||
: this()
|
||||
{
|
||||
blobCounter.MinWidth = minWidth;
|
||||
blobCounter.MinHeight = minHeight;
|
||||
blobCounter.MaxWidth = maxWidth;
|
||||
blobCounter.MaxHeight = maxHeight;
|
||||
blobCounter.CoupledSizeFiltering = coupledSizeFiltering;
|
||||
}
|
||||
|
||||
public BlobsFiltering(IBlobsFilter blobsFilter)
|
||||
: this()
|
||||
{
|
||||
blobCounter.BlobsFilter = blobsFilter;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image)
|
||||
{
|
||||
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0041: Invalid comparison between Unknown and I4
|
||||
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
|
||||
blobCounter.ProcessImage(image);
|
||||
int[] objectLabels = blobCounter.ObjectLabels;
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
if ((int)image.PixelFormat == 198659)
|
||||
{
|
||||
int num = image.Stride - width;
|
||||
int i = 0;
|
||||
int num2 = 0;
|
||||
for (; i < height; i++)
|
||||
{
|
||||
int num3 = 0;
|
||||
while (num3 < width)
|
||||
{
|
||||
if (objectLabels[num2] == 0)
|
||||
{
|
||||
*ptr = 0;
|
||||
}
|
||||
num3++;
|
||||
ptr++;
|
||||
num2++;
|
||||
}
|
||||
ptr += num;
|
||||
}
|
||||
return;
|
||||
}
|
||||
int num4 = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
int num5 = image.Stride - width * num4;
|
||||
int j = 0;
|
||||
int num6 = 0;
|
||||
for (; j < height; j++)
|
||||
{
|
||||
int num7 = 0;
|
||||
while (num7 < width)
|
||||
{
|
||||
if (objectLabels[num6] == 0)
|
||||
{
|
||||
ptr[2] = (ptr[1] = (*ptr = 0));
|
||||
}
|
||||
num7++;
|
||||
ptr += num4;
|
||||
num6++;
|
||||
}
|
||||
ptr += num5;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public sealed class Blur : Convolution
|
||||
{
|
||||
public Blur()
|
||||
: base(new int[5, 5]
|
||||
{
|
||||
{ 1, 2, 3, 2, 1 },
|
||||
{ 2, 4, 5, 4, 2 },
|
||||
{ 3, 5, 6, 5, 3 },
|
||||
{ 2, 4, 5, 4, 2 },
|
||||
{ 1, 2, 3, 2, 1 }
|
||||
})
|
||||
{
|
||||
base.ProcessAlpha = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class BottomHat : BaseInPlaceFilter
|
||||
{
|
||||
private Closing closing = new Closing();
|
||||
|
||||
private Subtract subtract = new Subtract();
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public BottomHat()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)1052676] = (PixelFormat)1052676;
|
||||
formatTranslations[(PixelFormat)1060876] = (PixelFormat)1060876;
|
||||
}
|
||||
|
||||
public BottomHat(short[,] se)
|
||||
: this()
|
||||
{
|
||||
closing = new Closing(se);
|
||||
}
|
||||
|
||||
protected override void ProcessFilter(UnmanagedImage image)
|
||||
{
|
||||
UnmanagedImage unmanagedImage = image.Clone();
|
||||
closing.ApplyInPlace(image);
|
||||
subtract.UnmanagedOverlayImage = unmanagedImage;
|
||||
subtract.ApplyInPlace(image);
|
||||
unmanagedImage.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class BradleyLocalThresholding : BaseInPlaceFilter
|
||||
{
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
private int windowSize = 41;
|
||||
|
||||
private float pixelBrightnessDifferenceLimit = 0.15f;
|
||||
|
||||
public int WindowSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return windowSize;
|
||||
}
|
||||
set
|
||||
{
|
||||
windowSize = System.Math.Max(3, value | 1);
|
||||
}
|
||||
}
|
||||
|
||||
public float PixelBrightnessDifferenceLimit
|
||||
{
|
||||
get
|
||||
{
|
||||
return pixelBrightnessDifferenceLimit;
|
||||
}
|
||||
set
|
||||
{
|
||||
pixelBrightnessDifferenceLimit = System.Math.Max(0f, System.Math.Min(1f, value));
|
||||
}
|
||||
}
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public BradleyLocalThresholding()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image)
|
||||
{
|
||||
IntegralImage integralImage = IntegralImage.FromBitmap(image);
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
int num = width - 1;
|
||||
int num2 = height - 1;
|
||||
int num3 = image.Stride - width;
|
||||
int num4 = windowSize / 2;
|
||||
float num5 = 1f - pixelBrightnessDifferenceLimit;
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
int num6 = i - num4;
|
||||
int num7 = i + num4;
|
||||
if (num6 < 0)
|
||||
{
|
||||
num6 = 0;
|
||||
}
|
||||
if (num7 > num2)
|
||||
{
|
||||
num7 = num2;
|
||||
}
|
||||
int num8 = 0;
|
||||
while (num8 < width)
|
||||
{
|
||||
int num9 = num8 - num4;
|
||||
int num10 = num8 + num4;
|
||||
if (num9 < 0)
|
||||
{
|
||||
num9 = 0;
|
||||
}
|
||||
if (num10 > num)
|
||||
{
|
||||
num10 = num;
|
||||
}
|
||||
*ptr = (byte)((*ptr >= (int)(integralImage.GetRectangleMeanUnsafe(num9, num6, num10, num7) * num5)) ? 255u : 0u);
|
||||
num8++;
|
||||
ptr++;
|
||||
}
|
||||
ptr += num3;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class BrightnessCorrection : BaseInPlacePartialFilter
|
||||
{
|
||||
private LevelsLinear baseFilter = new LevelsLinear();
|
||||
|
||||
private int adjustValue;
|
||||
|
||||
public int AdjustValue
|
||||
{
|
||||
get
|
||||
{
|
||||
return adjustValue;
|
||||
}
|
||||
set
|
||||
{
|
||||
adjustValue = System.Math.Max(-255, System.Math.Min(255, value));
|
||||
if (adjustValue > 0)
|
||||
{
|
||||
LevelsLinear levelsLinear = baseFilter;
|
||||
LevelsLinear levelsLinear2 = baseFilter;
|
||||
LevelsLinear levelsLinear3 = baseFilter;
|
||||
IntRange intRange = (baseFilter.InGray = new IntRange(0, 255 - adjustValue));
|
||||
IntRange intRange3 = (levelsLinear3.InBlue = intRange);
|
||||
IntRange inRed = (levelsLinear2.InGreen = intRange3);
|
||||
levelsLinear.InRed = inRed;
|
||||
LevelsLinear levelsLinear4 = baseFilter;
|
||||
LevelsLinear levelsLinear5 = baseFilter;
|
||||
LevelsLinear levelsLinear6 = baseFilter;
|
||||
IntRange intRange6 = (baseFilter.OutGray = new IntRange(adjustValue, 255));
|
||||
IntRange intRange8 = (levelsLinear6.OutBlue = intRange6);
|
||||
IntRange outRed = (levelsLinear5.OutGreen = intRange8);
|
||||
levelsLinear4.OutRed = outRed;
|
||||
}
|
||||
else
|
||||
{
|
||||
LevelsLinear levelsLinear7 = baseFilter;
|
||||
LevelsLinear levelsLinear8 = baseFilter;
|
||||
LevelsLinear levelsLinear9 = baseFilter;
|
||||
IntRange intRange11 = (baseFilter.InGray = new IntRange(-adjustValue, 255));
|
||||
IntRange intRange13 = (levelsLinear9.InBlue = intRange11);
|
||||
IntRange inRed2 = (levelsLinear8.InGreen = intRange13);
|
||||
levelsLinear7.InRed = inRed2;
|
||||
LevelsLinear levelsLinear10 = baseFilter;
|
||||
LevelsLinear levelsLinear11 = baseFilter;
|
||||
LevelsLinear levelsLinear12 = baseFilter;
|
||||
IntRange intRange16 = (baseFilter.OutGray = new IntRange(0, 255 + adjustValue));
|
||||
IntRange intRange18 = (levelsLinear12.OutBlue = intRange16);
|
||||
IntRange outRed2 = (levelsLinear11.OutGreen = intRange18);
|
||||
levelsLinear10.OutRed = outRed2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => baseFilter.FormatTranslations;
|
||||
|
||||
public BrightnessCorrection()
|
||||
{
|
||||
AdjustValue = 10;
|
||||
}
|
||||
|
||||
public BrightnessCorrection(int adjustValue)
|
||||
{
|
||||
AdjustValue = adjustValue;
|
||||
}
|
||||
|
||||
protected override void ProcessFilter(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
baseFilter.ApplyInPlace(image, rect);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public sealed class BurkesDithering : ErrorDiffusionToAdjacentNeighbors
|
||||
{
|
||||
public BurkesDithering()
|
||||
: base(new int[2][]
|
||||
{
|
||||
new int[2] { 8, 4 },
|
||||
new int[5] { 2, 4, 8, 4, 2 }
|
||||
})
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class CannyEdgeDetector : BaseUsingCopyPartialFilter
|
||||
{
|
||||
private GaussianBlur gaussianFilter = new GaussianBlur();
|
||||
|
||||
private byte lowThreshold = 20;
|
||||
|
||||
private byte highThreshold = 100;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public byte LowThreshold
|
||||
{
|
||||
get
|
||||
{
|
||||
return lowThreshold;
|
||||
}
|
||||
set
|
||||
{
|
||||
lowThreshold = value;
|
||||
}
|
||||
}
|
||||
|
||||
public byte HighThreshold
|
||||
{
|
||||
get
|
||||
{
|
||||
return highThreshold;
|
||||
}
|
||||
set
|
||||
{
|
||||
highThreshold = value;
|
||||
}
|
||||
}
|
||||
|
||||
public double GaussianSigma
|
||||
{
|
||||
get
|
||||
{
|
||||
return gaussianFilter.Sigma;
|
||||
}
|
||||
set
|
||||
{
|
||||
gaussianFilter.Sigma = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int GaussianSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return gaussianFilter.Size;
|
||||
}
|
||||
set
|
||||
{
|
||||
gaussianFilter.Size = value;
|
||||
}
|
||||
}
|
||||
|
||||
public CannyEdgeDetector()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
}
|
||||
|
||||
public CannyEdgeDetector(byte lowThreshold, byte highThreshold)
|
||||
: this()
|
||||
{
|
||||
this.lowThreshold = lowThreshold;
|
||||
this.highThreshold = highThreshold;
|
||||
}
|
||||
|
||||
public CannyEdgeDetector(byte lowThreshold, byte highThreshold, double sigma)
|
||||
: this()
|
||||
{
|
||||
this.lowThreshold = lowThreshold;
|
||||
this.highThreshold = highThreshold;
|
||||
gaussianFilter.Sigma = sigma;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage source, UnmanagedImage destination, Rectangle rect)
|
||||
{
|
||||
int num = rect.Left + 1;
|
||||
int num2 = rect.Top + 1;
|
||||
int num3 = num + rect.Width - 2;
|
||||
int num4 = num2 + rect.Height - 2;
|
||||
int num5 = rect.Width - 2;
|
||||
int num6 = rect.Height - 2;
|
||||
int stride = destination.Stride;
|
||||
int stride2 = source.Stride;
|
||||
int num7 = stride - rect.Width + 2;
|
||||
int num8 = stride2 - rect.Width + 2;
|
||||
double num9 = 180.0 / System.Math.PI;
|
||||
float num10 = 0f;
|
||||
float num11 = 0f;
|
||||
UnmanagedImage unmanagedImage = gaussianFilter.Apply(source);
|
||||
byte[] array = new byte[num5 * num6];
|
||||
float[,] array2 = new float[source.Width, source.Height];
|
||||
float num12 = float.NegativeInfinity;
|
||||
byte* ptr = (byte*)unmanagedImage.ImageData.ToPointer();
|
||||
ptr += stride2 * num2 + num;
|
||||
int num13 = 0;
|
||||
for (int i = num2; i < num4; i++)
|
||||
{
|
||||
int num14 = num;
|
||||
while (num14 < num3)
|
||||
{
|
||||
int num15 = ptr[-stride2 + 1] + ptr[stride2 + 1] - ptr[-stride2 - 1] - ptr[stride2 - 1] + 2 * (ptr[1] - ptr[-1]);
|
||||
int num16 = ptr[-stride2 - 1] + ptr[-stride2 + 1] - ptr[stride2 - 1] - ptr[stride2 + 1] + 2 * (ptr[-stride2] - ptr[stride2]);
|
||||
array2[num14, i] = (float)System.Math.Sqrt(num15 * num15 + num16 * num16);
|
||||
if (array2[num14, i] > num12)
|
||||
{
|
||||
num12 = array2[num14, i];
|
||||
}
|
||||
double num17;
|
||||
if (num15 == 0)
|
||||
{
|
||||
num17 = ((num16 != 0) ? 90 : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
double num18 = (double)num16 / (double)num15;
|
||||
num17 = ((!(num18 < 0.0)) ? (System.Math.Atan(num18) * num9) : (180.0 - System.Math.Atan(0.0 - num18) * num9));
|
||||
num17 = ((!(num17 < 22.5)) ? ((!(num17 < 67.5)) ? ((!(num17 < 112.5)) ? ((!(num17 < 157.5)) ? 0.0 : 135.0) : 90.0) : 45.0) : 0.0);
|
||||
}
|
||||
array[num13] = (byte)num17;
|
||||
num14++;
|
||||
ptr++;
|
||||
num13++;
|
||||
}
|
||||
ptr += num8;
|
||||
}
|
||||
byte* ptr2 = (byte*)destination.ImageData.ToPointer();
|
||||
ptr2 += stride * num2 + num;
|
||||
num13 = 0;
|
||||
for (int j = num2; j < num4; j++)
|
||||
{
|
||||
int num19 = num;
|
||||
while (num19 < num3)
|
||||
{
|
||||
switch (array[num13])
|
||||
{
|
||||
case 0:
|
||||
num10 = array2[num19 - 1, j];
|
||||
num11 = array2[num19 + 1, j];
|
||||
break;
|
||||
case 45:
|
||||
num10 = array2[num19 - 1, j + 1];
|
||||
num11 = array2[num19 + 1, j - 1];
|
||||
break;
|
||||
case 90:
|
||||
num10 = array2[num19, j + 1];
|
||||
num11 = array2[num19, j - 1];
|
||||
break;
|
||||
case 135:
|
||||
num10 = array2[num19 + 1, j + 1];
|
||||
num11 = array2[num19 - 1, j - 1];
|
||||
break;
|
||||
}
|
||||
if (array2[num19, j] < num10 || array2[num19, j] < num11)
|
||||
{
|
||||
*ptr2 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr2 = (byte)(array2[num19, j] / num12 * 255f);
|
||||
}
|
||||
num19++;
|
||||
ptr2++;
|
||||
num13++;
|
||||
}
|
||||
ptr2 += num7;
|
||||
}
|
||||
ptr2 = (byte*)destination.ImageData.ToPointer();
|
||||
ptr2 += stride * num2 + num;
|
||||
for (int k = num2; k < num4; k++)
|
||||
{
|
||||
int num20 = num;
|
||||
while (num20 < num3)
|
||||
{
|
||||
if (*ptr2 < highThreshold)
|
||||
{
|
||||
if (*ptr2 < lowThreshold)
|
||||
{
|
||||
*ptr2 = 0;
|
||||
}
|
||||
else if (ptr2[-1] < highThreshold && ptr2[1] < highThreshold && ptr2[-stride - 1] < highThreshold && ptr2[-stride] < highThreshold && ptr2[-stride + 1] < highThreshold && ptr2[stride - 1] < highThreshold && ptr2[stride] < highThreshold && ptr2[stride + 1] < highThreshold)
|
||||
{
|
||||
*ptr2 = 0;
|
||||
}
|
||||
}
|
||||
num20++;
|
||||
ptr2++;
|
||||
}
|
||||
ptr2 += num7;
|
||||
}
|
||||
Drawing.Rectangle(destination, rect, Color.Black);
|
||||
unmanagedImage.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class CanvasCrop : BaseInPlaceFilter
|
||||
{
|
||||
private byte fillRed = byte.MaxValue;
|
||||
|
||||
private byte fillGreen = byte.MaxValue;
|
||||
|
||||
private byte fillBlue = byte.MaxValue;
|
||||
|
||||
private byte fillGray = byte.MaxValue;
|
||||
|
||||
private Rectangle region;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public Color FillColorRGB
|
||||
{
|
||||
get
|
||||
{
|
||||
return Color.FromArgb(fillRed, fillGreen, fillBlue);
|
||||
}
|
||||
set
|
||||
{
|
||||
fillRed = value.R;
|
||||
fillGreen = value.G;
|
||||
fillBlue = value.B;
|
||||
}
|
||||
}
|
||||
|
||||
public byte FillColorGray
|
||||
{
|
||||
get
|
||||
{
|
||||
return fillGray;
|
||||
}
|
||||
set
|
||||
{
|
||||
fillGray = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Rectangle Region
|
||||
{
|
||||
get
|
||||
{
|
||||
return region;
|
||||
}
|
||||
set
|
||||
{
|
||||
region = value;
|
||||
}
|
||||
}
|
||||
|
||||
private CanvasCrop()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
}
|
||||
|
||||
public CanvasCrop(Rectangle region)
|
||||
: this()
|
||||
{
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
public CanvasCrop(Rectangle region, Color fillColorRGB)
|
||||
: this()
|
||||
{
|
||||
this.region = region;
|
||||
fillRed = fillColorRGB.R;
|
||||
fillGreen = fillColorRGB.G;
|
||||
fillBlue = fillColorRGB.B;
|
||||
}
|
||||
|
||||
public CanvasCrop(Rectangle region, byte fillColorGray)
|
||||
: this()
|
||||
{
|
||||
this.region = region;
|
||||
fillGray = fillColorGray;
|
||||
}
|
||||
|
||||
public CanvasCrop(Rectangle region, Color fillColorRGB, byte fillColorGray)
|
||||
: this()
|
||||
{
|
||||
this.region = region;
|
||||
fillRed = fillColorRGB.R;
|
||||
fillGreen = fillColorRGB.G;
|
||||
fillBlue = fillColorRGB.B;
|
||||
fillGray = fillColorGray;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0043: Invalid comparison between Unknown and I4
|
||||
int num = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
int num2 = image.Stride - width * num;
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
if ((int)image.PixelFormat == 198659)
|
||||
{
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
int num3 = 0;
|
||||
while (num3 < width)
|
||||
{
|
||||
if (!region.Contains(num3, i))
|
||||
{
|
||||
*ptr = fillGray;
|
||||
}
|
||||
num3++;
|
||||
ptr++;
|
||||
}
|
||||
ptr += num2;
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
int num4 = 0;
|
||||
while (num4 < width)
|
||||
{
|
||||
if (!region.Contains(num4, j))
|
||||
{
|
||||
ptr[2] = fillRed;
|
||||
ptr[1] = fillGreen;
|
||||
*ptr = fillBlue;
|
||||
}
|
||||
num4++;
|
||||
ptr += num;
|
||||
}
|
||||
ptr += num2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class CanvasFill : BaseInPlaceFilter
|
||||
{
|
||||
private byte fillRed = byte.MaxValue;
|
||||
|
||||
private byte fillGreen = byte.MaxValue;
|
||||
|
||||
private byte fillBlue = byte.MaxValue;
|
||||
|
||||
private byte fillGray = byte.MaxValue;
|
||||
|
||||
private Rectangle region;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public Color FillColorRGB
|
||||
{
|
||||
get
|
||||
{
|
||||
return Color.FromArgb(fillRed, fillGreen, fillBlue);
|
||||
}
|
||||
set
|
||||
{
|
||||
fillRed = value.R;
|
||||
fillGreen = value.G;
|
||||
fillBlue = value.B;
|
||||
}
|
||||
}
|
||||
|
||||
public byte FillColorGray
|
||||
{
|
||||
get
|
||||
{
|
||||
return fillGray;
|
||||
}
|
||||
set
|
||||
{
|
||||
fillGray = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Rectangle Region
|
||||
{
|
||||
get
|
||||
{
|
||||
return region;
|
||||
}
|
||||
set
|
||||
{
|
||||
region = value;
|
||||
}
|
||||
}
|
||||
|
||||
private CanvasFill()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
}
|
||||
|
||||
public CanvasFill(Rectangle region)
|
||||
: this()
|
||||
{
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
public CanvasFill(Rectangle region, Color fillColorRGB)
|
||||
: this()
|
||||
{
|
||||
this.region = region;
|
||||
fillRed = fillColorRGB.R;
|
||||
fillGreen = fillColorRGB.G;
|
||||
fillBlue = fillColorRGB.B;
|
||||
}
|
||||
|
||||
public CanvasFill(Rectangle region, byte fillColorGray)
|
||||
: this()
|
||||
{
|
||||
this.region = region;
|
||||
fillGray = fillColorGray;
|
||||
}
|
||||
|
||||
public CanvasFill(Rectangle region, Color fillColorRGB, byte fillColorGray)
|
||||
: this()
|
||||
{
|
||||
this.region = region;
|
||||
fillRed = fillColorRGB.R;
|
||||
fillGreen = fillColorRGB.G;
|
||||
fillBlue = fillColorRGB.B;
|
||||
fillGray = fillColorGray;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00ad: Invalid comparison between Unknown and I4
|
||||
int num = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
int num2 = System.Math.Max(0, region.X);
|
||||
int num3 = System.Math.Max(0, region.Y);
|
||||
if (num2 >= width || num3 >= height)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int num4 = System.Math.Min(width, region.Right);
|
||||
int num5 = System.Math.Min(height, region.Bottom);
|
||||
if (num4 <= num2 || num5 <= num3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int stride = image.Stride;
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer() + (nint)num3 * (nint)stride + (nint)num2 * (nint)num;
|
||||
if ((int)image.PixelFormat == 198659)
|
||||
{
|
||||
int count = num4 - num2;
|
||||
for (int i = num3; i < num5; i++)
|
||||
{
|
||||
SystemTools.SetUnmanagedMemory(ptr, fillGray, count);
|
||||
ptr += stride;
|
||||
}
|
||||
return;
|
||||
}
|
||||
int num6 = stride - (num4 - num2) * num;
|
||||
for (int j = num3; j < num5; j++)
|
||||
{
|
||||
int num7 = num2;
|
||||
while (num7 < num4)
|
||||
{
|
||||
ptr[2] = fillRed;
|
||||
ptr[1] = fillGreen;
|
||||
*ptr = fillBlue;
|
||||
num7++;
|
||||
ptr += num;
|
||||
}
|
||||
ptr += num6;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class CanvasMove : BaseInPlaceFilter
|
||||
{
|
||||
private byte fillRed = byte.MaxValue;
|
||||
|
||||
private byte fillGreen = byte.MaxValue;
|
||||
|
||||
private byte fillBlue = byte.MaxValue;
|
||||
|
||||
private byte fillAlpha = byte.MaxValue;
|
||||
|
||||
private byte fillGray = byte.MaxValue;
|
||||
|
||||
private IntPoint movePoint;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public Color FillColorRGB
|
||||
{
|
||||
get
|
||||
{
|
||||
return Color.FromArgb(fillAlpha, fillRed, fillGreen, fillBlue);
|
||||
}
|
||||
set
|
||||
{
|
||||
fillRed = value.R;
|
||||
fillGreen = value.G;
|
||||
fillBlue = value.B;
|
||||
fillAlpha = value.A;
|
||||
}
|
||||
}
|
||||
|
||||
public byte FillColorGray
|
||||
{
|
||||
get
|
||||
{
|
||||
return fillGray;
|
||||
}
|
||||
set
|
||||
{
|
||||
fillGray = value;
|
||||
}
|
||||
}
|
||||
|
||||
public IntPoint MovePoint
|
||||
{
|
||||
get
|
||||
{
|
||||
return movePoint;
|
||||
}
|
||||
set
|
||||
{
|
||||
movePoint = value;
|
||||
}
|
||||
}
|
||||
|
||||
private CanvasMove()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)1052676] = (PixelFormat)1052676;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)1060876] = (PixelFormat)1060876;
|
||||
formatTranslations[(PixelFormat)3424269] = (PixelFormat)3424269;
|
||||
}
|
||||
|
||||
public CanvasMove(IntPoint movePoint)
|
||||
: this()
|
||||
{
|
||||
this.movePoint = movePoint;
|
||||
}
|
||||
|
||||
public CanvasMove(IntPoint movePoint, Color fillColorRGB)
|
||||
: this()
|
||||
{
|
||||
this.movePoint = movePoint;
|
||||
fillRed = fillColorRGB.R;
|
||||
fillGreen = fillColorRGB.G;
|
||||
fillBlue = fillColorRGB.B;
|
||||
fillAlpha = fillColorRGB.A;
|
||||
}
|
||||
|
||||
public CanvasMove(IntPoint movePoint, byte fillColorGray)
|
||||
: this()
|
||||
{
|
||||
this.movePoint = movePoint;
|
||||
fillGray = fillColorGray;
|
||||
}
|
||||
|
||||
public CanvasMove(IntPoint movePoint, Color fillColorRGB, byte fillColorGray)
|
||||
: this()
|
||||
{
|
||||
this.movePoint = movePoint;
|
||||
fillRed = fillColorRGB.R;
|
||||
fillGreen = fillColorRGB.G;
|
||||
fillBlue = fillColorRGB.B;
|
||||
fillAlpha = fillColorRGB.A;
|
||||
fillGray = fillColorGray;
|
||||
}
|
||||
|
||||
protected override void ProcessFilter(UnmanagedImage image)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
switch (Image.GetPixelFormatSize(image.PixelFormat) / 8)
|
||||
{
|
||||
case 1:
|
||||
case 3:
|
||||
case 4:
|
||||
ProcessFilter8bpc(image);
|
||||
break;
|
||||
case 2:
|
||||
case 6:
|
||||
case 8:
|
||||
ProcessFilter16bpc(image);
|
||||
break;
|
||||
case 5:
|
||||
case 7:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void ProcessFilter8bpc(UnmanagedImage image)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00ac: Invalid comparison between Unknown and I4
|
||||
int num = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
bool flag = num == 4;
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
int stride = image.Stride;
|
||||
int x = movePoint.X;
|
||||
int y = movePoint.Y;
|
||||
Rectangle rectangle = Rectangle.Intersect(new Rectangle(0, 0, width, height), new Rectangle(x, y, width, height));
|
||||
int num2 = 0;
|
||||
int num3 = height;
|
||||
int num4 = 1;
|
||||
int num5 = 0;
|
||||
int num6 = width;
|
||||
int num7 = 1;
|
||||
if (y > 0)
|
||||
{
|
||||
num2 = height - 1;
|
||||
num3 = -1;
|
||||
num4 = -1;
|
||||
}
|
||||
if (x > 0)
|
||||
{
|
||||
num5 = width - 1;
|
||||
num6 = -1;
|
||||
num7 = -1;
|
||||
}
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
if ((int)image.PixelFormat == 198659)
|
||||
{
|
||||
for (int i = num2; i != num3; i += num4)
|
||||
{
|
||||
for (int j = num5; j != num6; j += num7)
|
||||
{
|
||||
byte* ptr2 = ptr + (nint)i * (nint)stride + j;
|
||||
if (rectangle.Contains(j, i))
|
||||
{
|
||||
byte* ptr3 = ptr + (nint)(i - y) * (nint)stride + (j - x);
|
||||
*ptr2 = *ptr3;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr2 = fillGray;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int k = num2; k != num3; k += num4)
|
||||
{
|
||||
for (int l = num5; l != num6; l += num7)
|
||||
{
|
||||
byte* ptr2 = ptr + (nint)k * (nint)stride + (nint)l * (nint)num;
|
||||
if (rectangle.Contains(l, k))
|
||||
{
|
||||
byte* ptr3 = ptr + (nint)(k - y) * (nint)stride + (nint)(l - x) * (nint)num;
|
||||
ptr2[2] = ptr3[2];
|
||||
ptr2[1] = ptr3[1];
|
||||
*ptr2 = *ptr3;
|
||||
if (flag)
|
||||
{
|
||||
ptr2[3] = ptr3[3];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr2[2] = fillRed;
|
||||
ptr2[1] = fillGreen;
|
||||
*ptr2 = fillBlue;
|
||||
if (flag)
|
||||
{
|
||||
ptr2[3] = fillAlpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void ProcessFilter16bpc(UnmanagedImage image)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00e0: Invalid comparison between Unknown and I4
|
||||
int num = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
bool flag = num == 8;
|
||||
ushort num2 = (ushort)(fillRed << 8);
|
||||
ushort num3 = (ushort)(fillGreen << 8);
|
||||
ushort num4 = (ushort)(fillBlue << 8);
|
||||
ushort num5 = (ushort)(fillAlpha << 8);
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
int stride = image.Stride;
|
||||
int x = movePoint.X;
|
||||
int y = movePoint.Y;
|
||||
Rectangle rectangle = Rectangle.Intersect(new Rectangle(0, 0, width, height), new Rectangle(x, y, width, height));
|
||||
int num6 = 0;
|
||||
int num7 = height;
|
||||
int num8 = 1;
|
||||
int num9 = 0;
|
||||
int num10 = width;
|
||||
int num11 = 1;
|
||||
if (y > 0)
|
||||
{
|
||||
num6 = height - 1;
|
||||
num7 = -1;
|
||||
num8 = -1;
|
||||
}
|
||||
if (x > 0)
|
||||
{
|
||||
num9 = width - 1;
|
||||
num10 = -1;
|
||||
num11 = -1;
|
||||
}
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
if ((int)image.PixelFormat == 1052676)
|
||||
{
|
||||
for (int i = num6; i != num7; i += num8)
|
||||
{
|
||||
for (int j = num9; j != num10; j += num11)
|
||||
{
|
||||
ushort* ptr2 = (ushort*)(ptr + (nint)i * (nint)stride) + j;
|
||||
if (rectangle.Contains(j, i))
|
||||
{
|
||||
ushort* ptr3 = (ushort*)(ptr + (nint)(i - y) * (nint)stride) + (j - x);
|
||||
*ptr2 = *ptr3;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr2 = fillGray;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int k = num6; k != num7; k += num8)
|
||||
{
|
||||
for (int l = num9; l != num10; l += num11)
|
||||
{
|
||||
ushort* ptr2 = (ushort*)(ptr + (nint)k * (nint)stride + (nint)l * (nint)num);
|
||||
if (rectangle.Contains(l, k))
|
||||
{
|
||||
ushort* ptr3 = (ushort*)(ptr + (nint)(k - y) * (nint)stride + (nint)(l - x) * (nint)num);
|
||||
ptr2[2] = ptr3[2];
|
||||
ptr2[1] = ptr3[1];
|
||||
*ptr2 = *ptr3;
|
||||
if (flag)
|
||||
{
|
||||
ptr2[3] = ptr3[3];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr2[2] = num2;
|
||||
ptr2[1] = num3;
|
||||
*ptr2 = num4;
|
||||
if (flag)
|
||||
{
|
||||
ptr2[3] = num5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class ChannelFiltering : BaseInPlacePartialFilter
|
||||
{
|
||||
private IntRange red = new IntRange(0, 255);
|
||||
|
||||
private IntRange green = new IntRange(0, 255);
|
||||
|
||||
private IntRange blue = new IntRange(0, 255);
|
||||
|
||||
private byte fillR;
|
||||
|
||||
private byte fillG;
|
||||
|
||||
private byte fillB;
|
||||
|
||||
private bool redFillOutsideRange = true;
|
||||
|
||||
private bool greenFillOutsideRange = true;
|
||||
|
||||
private bool blueFillOutsideRange = true;
|
||||
|
||||
private byte[] mapRed = new byte[256];
|
||||
|
||||
private byte[] mapGreen = new byte[256];
|
||||
|
||||
private byte[] mapBlue = new byte[256];
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public IntRange Red
|
||||
{
|
||||
get
|
||||
{
|
||||
return red;
|
||||
}
|
||||
set
|
||||
{
|
||||
red = value;
|
||||
CalculateMap(red, fillR, redFillOutsideRange, mapRed);
|
||||
}
|
||||
}
|
||||
|
||||
public byte FillRed
|
||||
{
|
||||
get
|
||||
{
|
||||
return fillR;
|
||||
}
|
||||
set
|
||||
{
|
||||
fillR = value;
|
||||
CalculateMap(red, fillR, redFillOutsideRange, mapRed);
|
||||
}
|
||||
}
|
||||
|
||||
public IntRange Green
|
||||
{
|
||||
get
|
||||
{
|
||||
return green;
|
||||
}
|
||||
set
|
||||
{
|
||||
green = value;
|
||||
CalculateMap(green, fillG, greenFillOutsideRange, mapGreen);
|
||||
}
|
||||
}
|
||||
|
||||
public byte FillGreen
|
||||
{
|
||||
get
|
||||
{
|
||||
return fillG;
|
||||
}
|
||||
set
|
||||
{
|
||||
fillG = value;
|
||||
CalculateMap(green, fillG, greenFillOutsideRange, mapGreen);
|
||||
}
|
||||
}
|
||||
|
||||
public IntRange Blue
|
||||
{
|
||||
get
|
||||
{
|
||||
return blue;
|
||||
}
|
||||
set
|
||||
{
|
||||
blue = value;
|
||||
CalculateMap(blue, fillB, blueFillOutsideRange, mapBlue);
|
||||
}
|
||||
}
|
||||
|
||||
public byte FillBlue
|
||||
{
|
||||
get
|
||||
{
|
||||
return fillB;
|
||||
}
|
||||
set
|
||||
{
|
||||
fillB = value;
|
||||
CalculateMap(blue, fillB, blueFillOutsideRange, mapBlue);
|
||||
}
|
||||
}
|
||||
|
||||
public bool RedFillOutsideRange
|
||||
{
|
||||
get
|
||||
{
|
||||
return redFillOutsideRange;
|
||||
}
|
||||
set
|
||||
{
|
||||
redFillOutsideRange = value;
|
||||
CalculateMap(red, fillR, redFillOutsideRange, mapRed);
|
||||
}
|
||||
}
|
||||
|
||||
public bool GreenFillOutsideRange
|
||||
{
|
||||
get
|
||||
{
|
||||
return greenFillOutsideRange;
|
||||
}
|
||||
set
|
||||
{
|
||||
greenFillOutsideRange = value;
|
||||
CalculateMap(green, fillG, greenFillOutsideRange, mapGreen);
|
||||
}
|
||||
}
|
||||
|
||||
public bool BlueFillOutsideRange
|
||||
{
|
||||
get
|
||||
{
|
||||
return blueFillOutsideRange;
|
||||
}
|
||||
set
|
||||
{
|
||||
blueFillOutsideRange = value;
|
||||
CalculateMap(blue, fillB, blueFillOutsideRange, mapBlue);
|
||||
}
|
||||
}
|
||||
|
||||
public ChannelFiltering()
|
||||
: this(new IntRange(0, 255), new IntRange(0, 255), new IntRange(0, 255))
|
||||
{
|
||||
}
|
||||
|
||||
public ChannelFiltering(IntRange red, IntRange green, IntRange blue)
|
||||
{
|
||||
Red = red;
|
||||
Green = green;
|
||||
Blue = blue;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
int num = (((int)image.PixelFormat == 137224) ? 3 : 4);
|
||||
int left = rect.Left;
|
||||
int top = rect.Top;
|
||||
int num2 = left + rect.Width;
|
||||
int num3 = top + rect.Height;
|
||||
int num4 = image.Stride - rect.Width * num;
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
ptr += top * image.Stride + left * num;
|
||||
for (int i = top; i < num3; i++)
|
||||
{
|
||||
int num5 = left;
|
||||
while (num5 < num2)
|
||||
{
|
||||
ptr[2] = mapRed[ptr[2]];
|
||||
ptr[1] = mapGreen[ptr[1]];
|
||||
*ptr = mapBlue[*ptr];
|
||||
num5++;
|
||||
ptr += num;
|
||||
}
|
||||
ptr += num4;
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateMap(IntRange range, byte fill, bool fillOutsideRange, byte[] map)
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
if (i >= range.Min && i <= range.Max)
|
||||
{
|
||||
map[i] = (fillOutsideRange ? ((byte)i) : fill);
|
||||
}
|
||||
else
|
||||
{
|
||||
map[i] = (fillOutsideRange ? fill : ((byte)i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class Closing : IFilter, IInPlaceFilter, IInPlacePartialFilter, IFilterInformation
|
||||
{
|
||||
private Erosion errosion = new Erosion();
|
||||
|
||||
private Dilatation dilatation = new Dilatation();
|
||||
|
||||
public Dictionary<PixelFormat, PixelFormat> FormatTranslations => errosion.FormatTranslations;
|
||||
|
||||
public Closing()
|
||||
{
|
||||
}
|
||||
|
||||
public Closing(short[,] se)
|
||||
{
|
||||
errosion = new Erosion(se);
|
||||
dilatation = new Dilatation(se);
|
||||
}
|
||||
|
||||
public Bitmap Apply(Bitmap image)
|
||||
{
|
||||
Bitmap val = dilatation.Apply(image);
|
||||
Bitmap result = errosion.Apply(val);
|
||||
((Image)val).Dispose();
|
||||
return result;
|
||||
}
|
||||
|
||||
public Bitmap Apply(BitmapData imageData)
|
||||
{
|
||||
Bitmap val = dilatation.Apply(imageData);
|
||||
Bitmap result = errosion.Apply(val);
|
||||
((Image)val).Dispose();
|
||||
return result;
|
||||
}
|
||||
|
||||
public UnmanagedImage Apply(UnmanagedImage image)
|
||||
{
|
||||
UnmanagedImage unmanagedImage = dilatation.Apply(image);
|
||||
errosion.ApplyInPlace(unmanagedImage);
|
||||
return unmanagedImage;
|
||||
}
|
||||
|
||||
public void Apply(UnmanagedImage sourceImage, UnmanagedImage destinationImage)
|
||||
{
|
||||
dilatation.Apply(sourceImage, destinationImage);
|
||||
errosion.ApplyInPlace(destinationImage);
|
||||
}
|
||||
|
||||
public void ApplyInPlace(Bitmap image)
|
||||
{
|
||||
dilatation.ApplyInPlace(image);
|
||||
errosion.ApplyInPlace(image);
|
||||
}
|
||||
|
||||
public void ApplyInPlace(BitmapData imageData)
|
||||
{
|
||||
dilatation.ApplyInPlace(imageData);
|
||||
errosion.ApplyInPlace(imageData);
|
||||
}
|
||||
|
||||
public void ApplyInPlace(UnmanagedImage image)
|
||||
{
|
||||
dilatation.ApplyInPlace(image);
|
||||
errosion.ApplyInPlace(image);
|
||||
}
|
||||
|
||||
public void ApplyInPlace(Bitmap image, Rectangle rect)
|
||||
{
|
||||
dilatation.ApplyInPlace(image, rect);
|
||||
errosion.ApplyInPlace(image, rect);
|
||||
}
|
||||
|
||||
public void ApplyInPlace(BitmapData imageData, Rectangle rect)
|
||||
{
|
||||
dilatation.ApplyInPlace(imageData, rect);
|
||||
errosion.ApplyInPlace(imageData, rect);
|
||||
}
|
||||
|
||||
public void ApplyInPlace(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
dilatation.ApplyInPlace(image, rect);
|
||||
errosion.ApplyInPlace(image, rect);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class ColorFiltering : BaseInPlacePartialFilter
|
||||
{
|
||||
private IntRange red = new IntRange(0, 255);
|
||||
|
||||
private IntRange green = new IntRange(0, 255);
|
||||
|
||||
private IntRange blue = new IntRange(0, 255);
|
||||
|
||||
private byte fillR;
|
||||
|
||||
private byte fillG;
|
||||
|
||||
private byte fillB;
|
||||
|
||||
private bool fillOutsideRange = true;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public IntRange Red
|
||||
{
|
||||
get
|
||||
{
|
||||
return red;
|
||||
}
|
||||
set
|
||||
{
|
||||
red = value;
|
||||
}
|
||||
}
|
||||
|
||||
public IntRange Green
|
||||
{
|
||||
get
|
||||
{
|
||||
return green;
|
||||
}
|
||||
set
|
||||
{
|
||||
green = value;
|
||||
}
|
||||
}
|
||||
|
||||
public IntRange Blue
|
||||
{
|
||||
get
|
||||
{
|
||||
return blue;
|
||||
}
|
||||
set
|
||||
{
|
||||
blue = value;
|
||||
}
|
||||
}
|
||||
|
||||
public RGB FillColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return new RGB(fillR, fillG, fillB);
|
||||
}
|
||||
set
|
||||
{
|
||||
fillR = value.Red;
|
||||
fillG = value.Green;
|
||||
fillB = value.Blue;
|
||||
}
|
||||
}
|
||||
|
||||
public bool FillOutsideRange
|
||||
{
|
||||
get
|
||||
{
|
||||
return fillOutsideRange;
|
||||
}
|
||||
set
|
||||
{
|
||||
fillOutsideRange = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ColorFiltering()
|
||||
{
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
}
|
||||
|
||||
public ColorFiltering(IntRange red, IntRange green, IntRange blue)
|
||||
: this()
|
||||
{
|
||||
this.red = red;
|
||||
this.green = green;
|
||||
this.blue = blue;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
int num = (((int)image.PixelFormat == 137224) ? 3 : 4);
|
||||
int left = rect.Left;
|
||||
int top = rect.Top;
|
||||
int num2 = left + rect.Width;
|
||||
int num3 = top + rect.Height;
|
||||
int num4 = image.Stride - rect.Width * num;
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
ptr += top * image.Stride + left * num;
|
||||
for (int i = top; i < num3; i++)
|
||||
{
|
||||
int num5 = left;
|
||||
while (num5 < num2)
|
||||
{
|
||||
byte b = ptr[2];
|
||||
byte b2 = ptr[1];
|
||||
byte b3 = *ptr;
|
||||
if (b >= red.Min && b <= red.Max && b2 >= green.Min && b2 <= green.Max && b3 >= blue.Min && b3 <= blue.Max)
|
||||
{
|
||||
if (!fillOutsideRange)
|
||||
{
|
||||
ptr[2] = fillR;
|
||||
ptr[1] = fillG;
|
||||
*ptr = fillB;
|
||||
}
|
||||
}
|
||||
else if (fillOutsideRange)
|
||||
{
|
||||
ptr[2] = fillR;
|
||||
ptr[1] = fillG;
|
||||
*ptr = fillB;
|
||||
}
|
||||
num5++;
|
||||
ptr += num;
|
||||
}
|
||||
ptr += num4;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class ColorRemapping : BaseInPlacePartialFilter
|
||||
{
|
||||
private byte[] redMap;
|
||||
|
||||
private byte[] greenMap;
|
||||
|
||||
private byte[] blueMap;
|
||||
|
||||
private byte[] grayMap;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public byte[] RedMap
|
||||
{
|
||||
get
|
||||
{
|
||||
return redMap;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null || value.Length != 256)
|
||||
{
|
||||
throw new ArgumentException("A map should be array with 256 value.");
|
||||
}
|
||||
redMap = value;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] GreenMap
|
||||
{
|
||||
get
|
||||
{
|
||||
return greenMap;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null || value.Length != 256)
|
||||
{
|
||||
throw new ArgumentException("A map should be array with 256 value.");
|
||||
}
|
||||
greenMap = value;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] BlueMap
|
||||
{
|
||||
get
|
||||
{
|
||||
return blueMap;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null || value.Length != 256)
|
||||
{
|
||||
throw new ArgumentException("A map should be array with 256 value.");
|
||||
}
|
||||
blueMap = value;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] GrayMap
|
||||
{
|
||||
get
|
||||
{
|
||||
return grayMap;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null || value.Length != 256)
|
||||
{
|
||||
throw new ArgumentException("A map should be array with 256 value.");
|
||||
}
|
||||
grayMap = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ColorRemapping()
|
||||
{
|
||||
redMap = new byte[256];
|
||||
greenMap = new byte[256];
|
||||
blueMap = new byte[256];
|
||||
grayMap = new byte[256];
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
redMap[i] = (greenMap[i] = (blueMap[i] = (grayMap[i] = (byte)i)));
|
||||
}
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
}
|
||||
|
||||
public ColorRemapping(byte[] redMap, byte[] greenMap, byte[] blueMap)
|
||||
: this()
|
||||
{
|
||||
RedMap = redMap;
|
||||
GreenMap = greenMap;
|
||||
BlueMap = blueMap;
|
||||
}
|
||||
|
||||
public ColorRemapping(byte[] grayMap)
|
||||
: this()
|
||||
{
|
||||
GrayMap = grayMap;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0072: Invalid comparison between Unknown and I4
|
||||
int num = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
int left = rect.Left;
|
||||
int top = rect.Top;
|
||||
int num2 = left + rect.Width;
|
||||
int num3 = top + rect.Height;
|
||||
int num4 = image.Stride - rect.Width * num;
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
ptr += top * image.Stride + left * num;
|
||||
if ((int)image.PixelFormat == 198659)
|
||||
{
|
||||
for (int i = top; i < num3; i++)
|
||||
{
|
||||
int num5 = left;
|
||||
while (num5 < num2)
|
||||
{
|
||||
*ptr = grayMap[*ptr];
|
||||
num5++;
|
||||
ptr++;
|
||||
}
|
||||
ptr += num4;
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int j = top; j < num3; j++)
|
||||
{
|
||||
int num6 = left;
|
||||
while (num6 < num2)
|
||||
{
|
||||
ptr[2] = redMap[ptr[2]];
|
||||
ptr[1] = greenMap[ptr[1]];
|
||||
*ptr = blueMap[*ptr];
|
||||
num6++;
|
||||
ptr += num;
|
||||
}
|
||||
ptr += num4;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class ConnectedComponentsLabeling : BaseFilter
|
||||
{
|
||||
private static Color[] colorTable = new Color[32]
|
||||
{
|
||||
Color.Red,
|
||||
Color.Green,
|
||||
Color.Blue,
|
||||
Color.Yellow,
|
||||
Color.Violet,
|
||||
Color.Brown,
|
||||
Color.Olive,
|
||||
Color.Cyan,
|
||||
Color.Magenta,
|
||||
Color.Gold,
|
||||
Color.Indigo,
|
||||
Color.Ivory,
|
||||
Color.HotPink,
|
||||
Color.DarkRed,
|
||||
Color.DarkGreen,
|
||||
Color.DarkBlue,
|
||||
Color.DarkSeaGreen,
|
||||
Color.Gray,
|
||||
Color.DarkKhaki,
|
||||
Color.DarkGray,
|
||||
Color.LimeGreen,
|
||||
Color.Tomato,
|
||||
Color.SteelBlue,
|
||||
Color.SkyBlue,
|
||||
Color.Silver,
|
||||
Color.Salmon,
|
||||
Color.SaddleBrown,
|
||||
Color.RosyBrown,
|
||||
Color.PowderBlue,
|
||||
Color.Plum,
|
||||
Color.PapayaWhip,
|
||||
Color.Orange
|
||||
};
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
private BlobCounterBase blobCounter = new BlobCounter();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public BlobCounterBase BlobCounter
|
||||
{
|
||||
get
|
||||
{
|
||||
return blobCounter;
|
||||
}
|
||||
set
|
||||
{
|
||||
blobCounter = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static Color[] ColorTable
|
||||
{
|
||||
get
|
||||
{
|
||||
return colorTable;
|
||||
}
|
||||
set
|
||||
{
|
||||
colorTable = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool FilterBlobs
|
||||
{
|
||||
get
|
||||
{
|
||||
return blobCounter.FilterBlobs;
|
||||
}
|
||||
set
|
||||
{
|
||||
blobCounter.FilterBlobs = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CoupledSizeFiltering
|
||||
{
|
||||
get
|
||||
{
|
||||
return blobCounter.CoupledSizeFiltering;
|
||||
}
|
||||
set
|
||||
{
|
||||
blobCounter.CoupledSizeFiltering = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int MinWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return blobCounter.MinWidth;
|
||||
}
|
||||
set
|
||||
{
|
||||
blobCounter.MinWidth = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int MinHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
return blobCounter.MinHeight;
|
||||
}
|
||||
set
|
||||
{
|
||||
blobCounter.MinHeight = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int MaxWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return blobCounter.MaxWidth;
|
||||
}
|
||||
set
|
||||
{
|
||||
blobCounter.MaxWidth = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int MaxHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
return blobCounter.MaxHeight;
|
||||
}
|
||||
set
|
||||
{
|
||||
blobCounter.MaxHeight = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int ObjectCount => blobCounter.ObjectsCount;
|
||||
|
||||
public ConnectedComponentsLabeling()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)925707] = (PixelFormat)137224;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
|
||||
{
|
||||
blobCounter.ProcessImage(sourceData);
|
||||
int[] objectLabels = blobCounter.ObjectLabels;
|
||||
int width = sourceData.Width;
|
||||
int height = sourceData.Height;
|
||||
int num = destinationData.Stride - width * 3;
|
||||
byte* ptr = (byte*)destinationData.ImageData.ToPointer();
|
||||
int num2 = 0;
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
int num3 = 0;
|
||||
while (num3 < width)
|
||||
{
|
||||
if (objectLabels[num2] != 0)
|
||||
{
|
||||
Color color = colorTable[(objectLabels[num2] - 1) % colorTable.Length];
|
||||
ptr[2] = color.R;
|
||||
ptr[1] = color.G;
|
||||
*ptr = color.B;
|
||||
}
|
||||
num3++;
|
||||
ptr += 3;
|
||||
num2++;
|
||||
}
|
||||
ptr += num;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class ConservativeSmoothing : BaseUsingCopyPartialFilter
|
||||
{
|
||||
private int size = 3;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public int KernelSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return size;
|
||||
}
|
||||
set
|
||||
{
|
||||
size = System.Math.Max(3, System.Math.Min(25, value | 1));
|
||||
}
|
||||
}
|
||||
|
||||
public ConservativeSmoothing()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
}
|
||||
|
||||
public ConservativeSmoothing(int size)
|
||||
: this()
|
||||
{
|
||||
KernelSize = size;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage source, UnmanagedImage destination, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00b0: Invalid comparison between Unknown and I4
|
||||
int num = Image.GetPixelFormatSize(source.PixelFormat) / 8;
|
||||
int left = rect.Left;
|
||||
int top = rect.Top;
|
||||
int num2 = left + rect.Width;
|
||||
int num3 = top + rect.Height;
|
||||
int stride = source.Stride;
|
||||
int stride2 = destination.Stride;
|
||||
int num4 = stride - rect.Width * num;
|
||||
int num5 = stride2 - rect.Width * num;
|
||||
int num6 = size >> 1;
|
||||
byte* ptr = (byte*)source.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destination.ImageData.ToPointer();
|
||||
ptr += top * stride + left * num;
|
||||
ptr2 += top * stride2 + left * num;
|
||||
if ((int)destination.PixelFormat == 198659)
|
||||
{
|
||||
for (int i = top; i < num3; i++)
|
||||
{
|
||||
int num7 = left;
|
||||
while (num7 < num2)
|
||||
{
|
||||
byte b = byte.MaxValue;
|
||||
byte b2 = 0;
|
||||
byte b3;
|
||||
for (int j = -num6; j <= num6; j++)
|
||||
{
|
||||
int num8 = i + j;
|
||||
if (num8 < top)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (num8 >= num3)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (int k = -num6; k <= num6; k++)
|
||||
{
|
||||
num8 = num7 + k;
|
||||
if (num8 >= left && j != k && num8 < num2)
|
||||
{
|
||||
b3 = ptr[j * stride + k];
|
||||
if (b3 < b)
|
||||
{
|
||||
b = b3;
|
||||
}
|
||||
if (b3 > b2)
|
||||
{
|
||||
b2 = b3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
b3 = *ptr;
|
||||
*ptr2 = ((b3 > b2) ? b2 : ((b3 < b) ? b : b3));
|
||||
num7++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
ptr += num4;
|
||||
ptr2 += num5;
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int l = top; l < num3; l++)
|
||||
{
|
||||
int num9 = left;
|
||||
while (num9 < num2)
|
||||
{
|
||||
byte b;
|
||||
byte b5;
|
||||
byte b4 = (b = (b5 = byte.MaxValue));
|
||||
byte b2;
|
||||
byte b7;
|
||||
byte b6 = (b2 = (b7 = 0));
|
||||
byte b3;
|
||||
for (int j = -num6; j <= num6; j++)
|
||||
{
|
||||
int num8 = l + j;
|
||||
if (num8 < top)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (num8 >= num3)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (int k = -num6; k <= num6; k++)
|
||||
{
|
||||
num8 = num9 + k;
|
||||
if (num8 >= left && j != k && num8 < num2)
|
||||
{
|
||||
byte* ptr3 = ptr + (j * stride + k * num);
|
||||
b3 = ptr3[2];
|
||||
if (b3 < b4)
|
||||
{
|
||||
b4 = b3;
|
||||
}
|
||||
if (b3 > b6)
|
||||
{
|
||||
b6 = b3;
|
||||
}
|
||||
b3 = ptr3[1];
|
||||
if (b3 < b)
|
||||
{
|
||||
b = b3;
|
||||
}
|
||||
if (b3 > b2)
|
||||
{
|
||||
b2 = b3;
|
||||
}
|
||||
b3 = *ptr3;
|
||||
if (b3 < b5)
|
||||
{
|
||||
b5 = b3;
|
||||
}
|
||||
if (b3 > b7)
|
||||
{
|
||||
b7 = b3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
b3 = ptr[2];
|
||||
ptr2[2] = ((b3 > b6) ? b6 : ((b3 < b4) ? b4 : b3));
|
||||
b3 = ptr[1];
|
||||
ptr2[1] = ((b3 > b2) ? b2 : ((b3 < b) ? b : b3));
|
||||
b3 = *ptr;
|
||||
*ptr2 = ((b3 > b7) ? b7 : ((b3 < b5) ? b5 : b3));
|
||||
num9++;
|
||||
ptr += num;
|
||||
ptr2 += num;
|
||||
}
|
||||
ptr += num4;
|
||||
ptr2 += num5;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class ContrastCorrection : BaseInPlacePartialFilter
|
||||
{
|
||||
private LevelsLinear baseFilter = new LevelsLinear();
|
||||
|
||||
private int factor;
|
||||
|
||||
public int Factor
|
||||
{
|
||||
get
|
||||
{
|
||||
return factor;
|
||||
}
|
||||
set
|
||||
{
|
||||
factor = System.Math.Max(-127, System.Math.Min(127, value));
|
||||
if (factor > 0)
|
||||
{
|
||||
LevelsLinear levelsLinear = baseFilter;
|
||||
LevelsLinear levelsLinear2 = baseFilter;
|
||||
LevelsLinear levelsLinear3 = baseFilter;
|
||||
IntRange intRange = (baseFilter.InGray = new IntRange(factor, 255 - factor));
|
||||
IntRange intRange3 = (levelsLinear3.InBlue = intRange);
|
||||
IntRange inRed = (levelsLinear2.InGreen = intRange3);
|
||||
levelsLinear.InRed = inRed;
|
||||
LevelsLinear levelsLinear4 = baseFilter;
|
||||
LevelsLinear levelsLinear5 = baseFilter;
|
||||
LevelsLinear levelsLinear6 = baseFilter;
|
||||
IntRange intRange6 = (baseFilter.OutGray = new IntRange(0, 255));
|
||||
IntRange intRange8 = (levelsLinear6.OutBlue = intRange6);
|
||||
IntRange outRed = (levelsLinear5.OutGreen = intRange8);
|
||||
levelsLinear4.OutRed = outRed;
|
||||
}
|
||||
else
|
||||
{
|
||||
LevelsLinear levelsLinear7 = baseFilter;
|
||||
LevelsLinear levelsLinear8 = baseFilter;
|
||||
LevelsLinear levelsLinear9 = baseFilter;
|
||||
IntRange intRange11 = (baseFilter.OutGray = new IntRange(-factor, 255 + factor));
|
||||
IntRange intRange13 = (levelsLinear9.OutBlue = intRange11);
|
||||
IntRange outRed2 = (levelsLinear8.OutGreen = intRange13);
|
||||
levelsLinear7.OutRed = outRed2;
|
||||
LevelsLinear levelsLinear10 = baseFilter;
|
||||
LevelsLinear levelsLinear11 = baseFilter;
|
||||
LevelsLinear levelsLinear12 = baseFilter;
|
||||
IntRange intRange16 = (baseFilter.InGray = new IntRange(0, 255));
|
||||
IntRange intRange18 = (levelsLinear12.InBlue = intRange16);
|
||||
IntRange inRed2 = (levelsLinear11.InGreen = intRange18);
|
||||
levelsLinear10.InRed = inRed2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => baseFilter.FormatTranslations;
|
||||
|
||||
public ContrastCorrection()
|
||||
{
|
||||
Factor = 10;
|
||||
}
|
||||
|
||||
public ContrastCorrection(int factor)
|
||||
{
|
||||
Factor = factor;
|
||||
}
|
||||
|
||||
protected override void ProcessFilter(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
baseFilter.ApplyInPlace(image, rect);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class ContrastStretch : BaseInPlacePartialFilter
|
||||
{
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public ContrastStretch()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_006c: Invalid comparison between Unknown and I4
|
||||
int num = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
int left = rect.Left;
|
||||
int top = rect.Top;
|
||||
int num2 = left + rect.Width;
|
||||
int num3 = top + rect.Height;
|
||||
int stride = image.Stride;
|
||||
int num4 = stride - rect.Width * num;
|
||||
LevelsLinear levelsLinear = new LevelsLinear();
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
if ((int)image.PixelFormat == 198659)
|
||||
{
|
||||
ptr += top * stride + left;
|
||||
byte b = byte.MaxValue;
|
||||
byte b2 = 0;
|
||||
for (int i = top; i < num3; i++)
|
||||
{
|
||||
int num5 = left;
|
||||
while (num5 < num2)
|
||||
{
|
||||
byte b3 = *ptr;
|
||||
if (b3 < b)
|
||||
{
|
||||
b = b3;
|
||||
}
|
||||
if (b3 > b2)
|
||||
{
|
||||
b2 = b3;
|
||||
}
|
||||
num5++;
|
||||
ptr++;
|
||||
}
|
||||
ptr += num4;
|
||||
}
|
||||
levelsLinear.InGray = new IntRange(b, b2);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr += top * stride + left * num;
|
||||
byte b4 = byte.MaxValue;
|
||||
byte b5 = byte.MaxValue;
|
||||
byte b6 = byte.MaxValue;
|
||||
byte b7 = 0;
|
||||
byte b8 = 0;
|
||||
byte b9 = 0;
|
||||
for (int j = top; j < num3; j++)
|
||||
{
|
||||
int num6 = left;
|
||||
while (num6 < num2)
|
||||
{
|
||||
byte b10 = ptr[2];
|
||||
if (b10 < b4)
|
||||
{
|
||||
b4 = b10;
|
||||
}
|
||||
if (b10 > b7)
|
||||
{
|
||||
b7 = b10;
|
||||
}
|
||||
b10 = ptr[1];
|
||||
if (b10 < b5)
|
||||
{
|
||||
b5 = b10;
|
||||
}
|
||||
if (b10 > b8)
|
||||
{
|
||||
b8 = b10;
|
||||
}
|
||||
b10 = *ptr;
|
||||
if (b10 < b6)
|
||||
{
|
||||
b6 = b10;
|
||||
}
|
||||
if (b10 > b9)
|
||||
{
|
||||
b9 = b10;
|
||||
}
|
||||
num6++;
|
||||
ptr += num;
|
||||
}
|
||||
ptr += num4;
|
||||
}
|
||||
levelsLinear.InRed = new IntRange(b4, b7);
|
||||
levelsLinear.InGreen = new IntRange(b5, b8);
|
||||
levelsLinear.InBlue = new IntRange(b6, b9);
|
||||
}
|
||||
levelsLinear.ApplyInPlace(image, rect);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,614 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class Convolution : BaseUsingCopyPartialFilter
|
||||
{
|
||||
private int[,] kernel;
|
||||
|
||||
private int divisor = 1;
|
||||
|
||||
private int threshold;
|
||||
|
||||
private int size;
|
||||
|
||||
private bool dynamicDivisorForEdges = true;
|
||||
|
||||
private bool processAlpha;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public int[,] Kernel
|
||||
{
|
||||
get
|
||||
{
|
||||
return kernel;
|
||||
}
|
||||
set
|
||||
{
|
||||
int length = value.GetLength(0);
|
||||
if (length != value.GetLength(1) || length < 3 || length > 99 || length % 2 == 0)
|
||||
{
|
||||
throw new ArgumentException("Invalid kernel size.");
|
||||
}
|
||||
kernel = value;
|
||||
size = length;
|
||||
}
|
||||
}
|
||||
|
||||
public int Divisor
|
||||
{
|
||||
get
|
||||
{
|
||||
return divisor;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
throw new ArgumentException("Divisor can not be equal to zero.");
|
||||
}
|
||||
divisor = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int Threshold
|
||||
{
|
||||
get
|
||||
{
|
||||
return threshold;
|
||||
}
|
||||
set
|
||||
{
|
||||
threshold = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool DynamicDivisorForEdges
|
||||
{
|
||||
get
|
||||
{
|
||||
return dynamicDivisorForEdges;
|
||||
}
|
||||
set
|
||||
{
|
||||
dynamicDivisorForEdges = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ProcessAlpha
|
||||
{
|
||||
get
|
||||
{
|
||||
return processAlpha;
|
||||
}
|
||||
set
|
||||
{
|
||||
processAlpha = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected Convolution()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)1052676] = (PixelFormat)1052676;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
formatTranslations[(PixelFormat)1060876] = (PixelFormat)1060876;
|
||||
formatTranslations[(PixelFormat)3424269] = (PixelFormat)3424269;
|
||||
}
|
||||
|
||||
public Convolution(int[,] kernel)
|
||||
: this()
|
||||
{
|
||||
Kernel = kernel;
|
||||
divisor = 0;
|
||||
int i = 0;
|
||||
for (int length = kernel.GetLength(0); i < length; i++)
|
||||
{
|
||||
int j = 0;
|
||||
for (int length2 = kernel.GetLength(1); j < length2; j++)
|
||||
{
|
||||
divisor += kernel[i, j];
|
||||
}
|
||||
}
|
||||
if (divisor == 0)
|
||||
{
|
||||
divisor = 1;
|
||||
}
|
||||
}
|
||||
|
||||
public Convolution(int[,] kernel, int divisor)
|
||||
: this()
|
||||
{
|
||||
Kernel = kernel;
|
||||
Divisor = divisor;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage source, UnmanagedImage destination, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_015c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0166: Invalid comparison between Unknown and I4
|
||||
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00b4: Invalid comparison between Unknown and I4
|
||||
int num = Image.GetPixelFormatSize(source.PixelFormat) / 8;
|
||||
int left = rect.Left;
|
||||
int top = rect.Top;
|
||||
int stopX = left + rect.Width;
|
||||
int stopY = top + rect.Height;
|
||||
if (num <= 4 && num != 2)
|
||||
{
|
||||
int stride = source.Stride;
|
||||
int stride2 = destination.Stride;
|
||||
int srcOffset = stride - rect.Width * num;
|
||||
int dstOffset = stride2 - rect.Width * num;
|
||||
byte* ptr = (byte*)source.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destination.ImageData.ToPointer();
|
||||
ptr += top * stride + left * num;
|
||||
ptr2 += top * stride2 + left * num;
|
||||
if ((int)destination.PixelFormat == 198659)
|
||||
{
|
||||
Process8bppImage(ptr, ptr2, stride, stride2, srcOffset, dstOffset, left, top, stopX, stopY);
|
||||
}
|
||||
else if (num == 3 || !processAlpha)
|
||||
{
|
||||
Process24bppImage(ptr, ptr2, stride, stride2, srcOffset, dstOffset, left, top, stopX, stopY, num);
|
||||
}
|
||||
else
|
||||
{
|
||||
Process32bppImage(ptr, ptr2, stride, stride2, srcOffset, dstOffset, left, top, stopX, stopY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
num /= 2;
|
||||
int dstStride = destination.Stride / 2;
|
||||
int srcStride = source.Stride / 2;
|
||||
ushort* ptr3 = (ushort*)source.ImageData.ToPointer();
|
||||
ushort* ptr4 = (ushort*)destination.ImageData.ToPointer();
|
||||
ptr3 += left * num;
|
||||
ptr4 += left * num;
|
||||
if ((int)source.PixelFormat == 1052676)
|
||||
{
|
||||
Process16bppImage(ptr3, ptr4, srcStride, dstStride, left, top, stopX, stopY);
|
||||
}
|
||||
else if (num == 3 || !processAlpha)
|
||||
{
|
||||
Process48bppImage(ptr3, ptr4, srcStride, dstStride, left, top, stopX, stopY, num);
|
||||
}
|
||||
else
|
||||
{
|
||||
Process64bppImage(ptr3, ptr4, srcStride, dstStride, left, top, stopX, stopY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void Process8bppImage(byte* src, byte* dst, int srcStride, int dstStride, int srcOffset, int dstOffset, int startX, int startY, int stopX, int stopY)
|
||||
{
|
||||
int num = size >> 1;
|
||||
int num2 = size * size;
|
||||
for (int i = startY; i < stopY; i++)
|
||||
{
|
||||
int num3 = startX;
|
||||
while (num3 < stopX)
|
||||
{
|
||||
long num5;
|
||||
int num6;
|
||||
long num4 = (num5 = (num6 = 0));
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
int num7 = j - num;
|
||||
int num8 = i + num7;
|
||||
if (num8 < startY)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (num8 >= stopY)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (int k = 0; k < size; k++)
|
||||
{
|
||||
int num9 = k - num;
|
||||
num8 = num3 + num9;
|
||||
if (num8 >= startX && num8 < stopX)
|
||||
{
|
||||
int num10 = kernel[j, k];
|
||||
num5 += num10;
|
||||
num4 += num10 * src[num7 * srcStride + num9];
|
||||
num6++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num6 == num2)
|
||||
{
|
||||
num5 = divisor;
|
||||
}
|
||||
else if (!dynamicDivisorForEdges)
|
||||
{
|
||||
num5 = divisor;
|
||||
}
|
||||
if (num5 != 0)
|
||||
{
|
||||
num4 /= num5;
|
||||
}
|
||||
num4 += threshold;
|
||||
*dst = (byte)((num4 > 255) ? 255 : ((num4 < 0) ? 0 : num4));
|
||||
num3++;
|
||||
src++;
|
||||
dst++;
|
||||
}
|
||||
src += srcOffset;
|
||||
dst += dstOffset;
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void Process24bppImage(byte* src, byte* dst, int srcStride, int dstStride, int srcOffset, int dstOffset, int startX, int startY, int stopX, int stopY, int pixelSize)
|
||||
{
|
||||
int num = size >> 1;
|
||||
int num2 = size * size;
|
||||
for (int i = startY; i < stopY; i++)
|
||||
{
|
||||
int num3 = startX;
|
||||
while (num3 < stopX)
|
||||
{
|
||||
long num7;
|
||||
int num8;
|
||||
long num5;
|
||||
long num6;
|
||||
long num4 = (num5 = (num6 = (num7 = (num8 = 0))));
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
int num9 = j - num;
|
||||
int num10 = i + num9;
|
||||
if (num10 < startY)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (num10 >= stopY)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (int k = 0; k < size; k++)
|
||||
{
|
||||
int num11 = k - num;
|
||||
num10 = num3 + num11;
|
||||
if (num10 >= startX && num10 < stopX)
|
||||
{
|
||||
int num12 = kernel[j, k];
|
||||
byte* ptr = src + (num9 * srcStride + num11 * pixelSize);
|
||||
num7 += num12;
|
||||
num4 += num12 * ptr[2];
|
||||
num5 += num12 * ptr[1];
|
||||
num6 += num12 * *ptr;
|
||||
num8++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num8 == num2)
|
||||
{
|
||||
num7 = divisor;
|
||||
}
|
||||
else if (!dynamicDivisorForEdges)
|
||||
{
|
||||
num7 = divisor;
|
||||
}
|
||||
if (num7 != 0)
|
||||
{
|
||||
num4 /= num7;
|
||||
num5 /= num7;
|
||||
num6 /= num7;
|
||||
}
|
||||
num4 += threshold;
|
||||
num5 += threshold;
|
||||
num6 += threshold;
|
||||
dst[2] = (byte)((num4 > 255) ? 255 : ((num4 < 0) ? 0 : num4));
|
||||
dst[1] = (byte)((num5 > 255) ? 255 : ((num5 < 0) ? 0 : num5));
|
||||
*dst = (byte)((num6 > 255) ? 255 : ((num6 < 0) ? 0 : num6));
|
||||
if (pixelSize == 4)
|
||||
{
|
||||
dst[3] = src[3];
|
||||
}
|
||||
num3++;
|
||||
src += pixelSize;
|
||||
dst += pixelSize;
|
||||
}
|
||||
src += srcOffset;
|
||||
dst += dstOffset;
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void Process32bppImage(byte* src, byte* dst, int srcStride, int dstStride, int srcOffset, int dstOffset, int startX, int startY, int stopX, int stopY)
|
||||
{
|
||||
int num = size >> 1;
|
||||
int num2 = size * size;
|
||||
for (int i = startY; i < stopY; i++)
|
||||
{
|
||||
int num3 = startX;
|
||||
while (num3 < stopX)
|
||||
{
|
||||
long num8;
|
||||
int num9;
|
||||
long num5;
|
||||
long num6;
|
||||
long num7;
|
||||
long num4 = (num5 = (num6 = (num7 = (num8 = (num9 = 0)))));
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
int num10 = j - num;
|
||||
int num11 = i + num10;
|
||||
if (num11 < startY)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (num11 >= stopY)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (int k = 0; k < size; k++)
|
||||
{
|
||||
int num12 = k - num;
|
||||
num11 = num3 + num12;
|
||||
if (num11 >= startX && num11 < stopX)
|
||||
{
|
||||
int num13 = kernel[j, k];
|
||||
byte* ptr = src + (num10 * srcStride + num12 * 4);
|
||||
num8 += num13;
|
||||
num4 += num13 * ptr[2];
|
||||
num5 += num13 * ptr[1];
|
||||
num6 += num13 * *ptr;
|
||||
num7 += num13 * ptr[3];
|
||||
num9++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num9 == num2)
|
||||
{
|
||||
num8 = divisor;
|
||||
}
|
||||
else if (!dynamicDivisorForEdges)
|
||||
{
|
||||
num8 = divisor;
|
||||
}
|
||||
if (num8 != 0)
|
||||
{
|
||||
num4 /= num8;
|
||||
num5 /= num8;
|
||||
num6 /= num8;
|
||||
num7 /= num8;
|
||||
}
|
||||
num4 += threshold;
|
||||
num5 += threshold;
|
||||
num6 += threshold;
|
||||
num7 += threshold;
|
||||
dst[2] = (byte)((num4 > 255) ? 255 : ((num4 < 0) ? 0 : num4));
|
||||
dst[1] = (byte)((num5 > 255) ? 255 : ((num5 < 0) ? 0 : num5));
|
||||
*dst = (byte)((num6 > 255) ? 255 : ((num6 < 0) ? 0 : num6));
|
||||
dst[3] = (byte)((num7 > 255) ? 255 : ((num7 < 0) ? 0 : num7));
|
||||
num3++;
|
||||
src += 4;
|
||||
dst += 4;
|
||||
}
|
||||
src += srcOffset;
|
||||
dst += dstOffset;
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void Process16bppImage(ushort* baseSrc, ushort* baseDst, int srcStride, int dstStride, int startX, int startY, int stopX, int stopY)
|
||||
{
|
||||
int num = size >> 1;
|
||||
int num2 = size * size;
|
||||
for (int i = startY; i < stopY; i++)
|
||||
{
|
||||
ushort* ptr = baseSrc + i * srcStride;
|
||||
ushort* ptr2 = baseDst + i * dstStride;
|
||||
int num3 = startX;
|
||||
while (num3 < stopX)
|
||||
{
|
||||
long num5;
|
||||
int num6;
|
||||
long num4 = (num5 = (num6 = 0));
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
int num7 = j - num;
|
||||
int num8 = i + num7;
|
||||
if (num8 < startY)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (num8 >= stopY)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (int k = 0; k < size; k++)
|
||||
{
|
||||
int num9 = k - num;
|
||||
num8 = num3 + num9;
|
||||
if (num8 >= startX && num8 < stopX)
|
||||
{
|
||||
int num10 = kernel[j, k];
|
||||
num5 += num10;
|
||||
num4 += num10 * ptr[num7 * srcStride + num9];
|
||||
num6++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num6 == num2)
|
||||
{
|
||||
num5 = divisor;
|
||||
}
|
||||
else if (!dynamicDivisorForEdges)
|
||||
{
|
||||
num5 = divisor;
|
||||
}
|
||||
if (num5 != 0)
|
||||
{
|
||||
num4 /= num5;
|
||||
}
|
||||
num4 += threshold;
|
||||
*ptr2 = (ushort)((num4 > 65535) ? 65535 : ((num4 < 0) ? 0 : num4));
|
||||
num3++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void Process48bppImage(ushort* baseSrc, ushort* baseDst, int srcStride, int dstStride, int startX, int startY, int stopX, int stopY, int pixelSize)
|
||||
{
|
||||
int num = size >> 1;
|
||||
int num2 = size * size;
|
||||
for (int i = startY; i < stopY; i++)
|
||||
{
|
||||
ushort* ptr = baseSrc + i * srcStride;
|
||||
ushort* ptr2 = baseDst + i * dstStride;
|
||||
int num3 = startX;
|
||||
while (num3 < stopX)
|
||||
{
|
||||
long num7;
|
||||
int num8;
|
||||
long num5;
|
||||
long num6;
|
||||
long num4 = (num5 = (num6 = (num7 = (num8 = 0))));
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
int num9 = j - num;
|
||||
int num10 = i + num9;
|
||||
if (num10 < startY)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (num10 >= stopY)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (int k = 0; k < size; k++)
|
||||
{
|
||||
int num11 = k - num;
|
||||
num10 = num3 + num11;
|
||||
if (num10 >= startX && num10 < stopX)
|
||||
{
|
||||
int num12 = kernel[j, k];
|
||||
ushort* ptr3 = ptr + (num9 * srcStride + num11 * pixelSize);
|
||||
num7 += num12;
|
||||
num4 += num12 * ptr3[2];
|
||||
num5 += num12 * ptr3[1];
|
||||
num6 += num12 * *ptr3;
|
||||
num8++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num8 == num2)
|
||||
{
|
||||
num7 = divisor;
|
||||
}
|
||||
else if (!dynamicDivisorForEdges)
|
||||
{
|
||||
num7 = divisor;
|
||||
}
|
||||
if (num7 != 0)
|
||||
{
|
||||
num4 /= num7;
|
||||
num5 /= num7;
|
||||
num6 /= num7;
|
||||
}
|
||||
num4 += threshold;
|
||||
num5 += threshold;
|
||||
num6 += threshold;
|
||||
ptr2[2] = (ushort)((num4 > 65535) ? 65535 : ((num4 < 0) ? 0 : num4));
|
||||
ptr2[1] = (ushort)((num5 > 65535) ? 65535 : ((num5 < 0) ? 0 : num5));
|
||||
*ptr2 = (ushort)((num6 > 65535) ? 65535 : ((num6 < 0) ? 0 : num6));
|
||||
if (pixelSize == 4)
|
||||
{
|
||||
ptr2[3] = ptr[3];
|
||||
}
|
||||
num3++;
|
||||
ptr += pixelSize;
|
||||
ptr2 += pixelSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void Process64bppImage(ushort* baseSrc, ushort* baseDst, int srcStride, int dstStride, int startX, int startY, int stopX, int stopY)
|
||||
{
|
||||
int num = size >> 1;
|
||||
int num2 = size * size;
|
||||
for (int i = startY; i < stopY; i++)
|
||||
{
|
||||
ushort* ptr = baseSrc + i * srcStride;
|
||||
ushort* ptr2 = baseDst + i * dstStride;
|
||||
int num3 = startX;
|
||||
while (num3 < stopX)
|
||||
{
|
||||
long num8;
|
||||
int num9;
|
||||
long num5;
|
||||
long num6;
|
||||
long num7;
|
||||
long num4 = (num5 = (num6 = (num7 = (num8 = (num9 = 0)))));
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
int num10 = j - num;
|
||||
int num11 = i + num10;
|
||||
if (num11 < startY)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (num11 >= stopY)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (int k = 0; k < size; k++)
|
||||
{
|
||||
int num12 = k - num;
|
||||
num11 = num3 + num12;
|
||||
if (num11 >= startX && num11 < stopX)
|
||||
{
|
||||
int num13 = kernel[j, k];
|
||||
ushort* ptr3 = ptr + (num10 * srcStride + num12 * 4);
|
||||
num8 += num13;
|
||||
num4 += num13 * ptr3[2];
|
||||
num5 += num13 * ptr3[1];
|
||||
num6 += num13 * *ptr3;
|
||||
num7 += num13 * ptr3[3];
|
||||
num9++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num9 == num2)
|
||||
{
|
||||
num8 = divisor;
|
||||
}
|
||||
else if (!dynamicDivisorForEdges)
|
||||
{
|
||||
num8 = divisor;
|
||||
}
|
||||
if (num8 != 0)
|
||||
{
|
||||
num4 /= num8;
|
||||
num5 /= num8;
|
||||
num6 /= num8;
|
||||
num7 /= num8;
|
||||
}
|
||||
num4 += threshold;
|
||||
num5 += threshold;
|
||||
num6 += threshold;
|
||||
num7 += threshold;
|
||||
ptr2[2] = (ushort)((num4 > 65535) ? 65535 : ((num4 < 0) ? 0 : num4));
|
||||
ptr2[1] = (ushort)((num5 > 65535) ? 65535 : ((num5 < 0) ? 0 : num5));
|
||||
*ptr2 = (ushort)((num6 > 65535) ? 65535 : ((num6 < 0) ? 0 : num6));
|
||||
ptr2[3] = (ushort)((num7 > 65535) ? 65535 : ((num7 < 0) ? 0 : num7));
|
||||
num3++;
|
||||
ptr += 4;
|
||||
ptr2 += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class CornersMarker : BaseInPlaceFilter
|
||||
{
|
||||
private Color markerColor = Color.White;
|
||||
|
||||
private ICornersDetector detector;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public Color MarkerColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return markerColor;
|
||||
}
|
||||
set
|
||||
{
|
||||
markerColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ICornersDetector Detector
|
||||
{
|
||||
get
|
||||
{
|
||||
return detector;
|
||||
}
|
||||
set
|
||||
{
|
||||
detector = value;
|
||||
}
|
||||
}
|
||||
|
||||
public CornersMarker(ICornersDetector detector)
|
||||
: this(detector, Color.White)
|
||||
{
|
||||
}
|
||||
|
||||
public CornersMarker(ICornersDetector detector, Color markerColor)
|
||||
{
|
||||
this.detector = detector;
|
||||
this.markerColor = markerColor;
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
}
|
||||
|
||||
protected override void ProcessFilter(UnmanagedImage image)
|
||||
{
|
||||
List<IntPoint> list = detector.ProcessImage(image);
|
||||
foreach (IntPoint item in list)
|
||||
{
|
||||
Drawing.FillRectangle(image, new Rectangle(item.X - 1, item.Y - 1, 3, 3), markerColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class Crop : BaseTransformationFilter
|
||||
{
|
||||
private Rectangle rect;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public Rectangle Rectangle
|
||||
{
|
||||
get
|
||||
{
|
||||
return rect;
|
||||
}
|
||||
set
|
||||
{
|
||||
rect = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Crop(Rectangle rect)
|
||||
{
|
||||
this.rect = rect;
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
formatTranslations[(PixelFormat)1052676] = (PixelFormat)1052676;
|
||||
formatTranslations[(PixelFormat)1060876] = (PixelFormat)1060876;
|
||||
formatTranslations[(PixelFormat)3424269] = (PixelFormat)3424269;
|
||||
}
|
||||
|
||||
protected override Size CalculateNewImageSize(UnmanagedImage sourceData)
|
||||
{
|
||||
return new Size(rect.Width, rect.Height);
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
|
||||
{
|
||||
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
|
||||
Rectangle rectangle = rect;
|
||||
rectangle.Intersect(new Rectangle(0, 0, sourceData.Width, sourceData.Height));
|
||||
int left = rectangle.Left;
|
||||
int top = rectangle.Top;
|
||||
int num = rectangle.Bottom - 1;
|
||||
int width = rectangle.Width;
|
||||
int stride = sourceData.Stride;
|
||||
int stride2 = destinationData.Stride;
|
||||
int num2 = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8;
|
||||
int count = width * num2;
|
||||
byte* ptr = (byte*)sourceData.ImageData.ToPointer() + (nint)top * (nint)stride + (nint)left * (nint)num2;
|
||||
byte* ptr2 = (byte*)destinationData.ImageData.ToPointer();
|
||||
if (rect.Top < 0)
|
||||
{
|
||||
ptr2 -= (nint)stride2 * (nint)rect.Top;
|
||||
}
|
||||
if (rect.Left < 0)
|
||||
{
|
||||
ptr2 -= (nint)num2 * (nint)rect.Left;
|
||||
}
|
||||
for (int i = top; i <= num; i++)
|
||||
{
|
||||
SystemTools.CopyUnmanagedMemory(ptr2, ptr, count);
|
||||
ptr += stride;
|
||||
ptr2 += stride2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public sealed class Difference : BaseInPlaceFilter2
|
||||
{
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public Difference()
|
||||
{
|
||||
InitFormatTranslations();
|
||||
}
|
||||
|
||||
public Difference(Bitmap overlayImage)
|
||||
: base(overlayImage)
|
||||
{
|
||||
InitFormatTranslations();
|
||||
}
|
||||
|
||||
public Difference(UnmanagedImage unmanagedOverlayImage)
|
||||
: base(unmanagedOverlayImage)
|
||||
{
|
||||
InitFormatTranslations();
|
||||
}
|
||||
|
||||
private void InitFormatTranslations()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
formatTranslations[(PixelFormat)1052676] = (PixelFormat)1052676;
|
||||
formatTranslations[(PixelFormat)1060876] = (PixelFormat)1060876;
|
||||
formatTranslations[(PixelFormat)3424269] = (PixelFormat)3424269;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image, UnmanagedImage overlay)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001b: Invalid comparison between Unknown and I4
|
||||
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_003e: Invalid comparison between Unknown and I4
|
||||
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0023: Invalid comparison between Unknown and I4
|
||||
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0046: Invalid comparison between Unknown and I4
|
||||
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002b: Invalid comparison between Unknown and I4
|
||||
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0033: Invalid comparison between Unknown and I4
|
||||
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00e9: Invalid comparison between Unknown and I4
|
||||
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00f1: Invalid comparison between Unknown and I4
|
||||
PixelFormat pixelFormat = image.PixelFormat;
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
if ((int)pixelFormat == 198659 || (int)pixelFormat == 137224 || (int)pixelFormat == 139273 || (int)pixelFormat == 2498570)
|
||||
{
|
||||
int num = (((int)pixelFormat == 198659) ? 1 : (((int)pixelFormat == 137224) ? 3 : 4));
|
||||
int num2 = width * num;
|
||||
int num3 = image.Stride - num2;
|
||||
int num4 = overlay.Stride - num2;
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)overlay.ImageData.ToPointer();
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
int num5 = 0;
|
||||
while (num5 < num2)
|
||||
{
|
||||
int num6 = *ptr - *ptr2;
|
||||
*ptr = ((num6 < 0) ? ((byte)(-num6)) : ((byte)num6));
|
||||
num5++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
ptr += num3;
|
||||
ptr2 += num4;
|
||||
}
|
||||
return;
|
||||
}
|
||||
int num7 = (((int)pixelFormat == 1052676) ? 1 : (((int)pixelFormat == 1060876) ? 3 : 4));
|
||||
int num8 = width * num7;
|
||||
int stride = image.Stride;
|
||||
int stride2 = overlay.Stride;
|
||||
byte* ptr3 = (byte*)image.ImageData.ToPointer();
|
||||
byte* ptr4 = (byte*)overlay.ImageData.ToPointer();
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
ushort* ptr5 = (ushort*)(ptr3 + (nint)j * (nint)stride);
|
||||
ushort* ptr6 = (ushort*)(ptr4 + (nint)j * (nint)stride2);
|
||||
int num9 = 0;
|
||||
while (num9 < num8)
|
||||
{
|
||||
int num6 = *ptr5 - *ptr6;
|
||||
*ptr5 = ((num6 < 0) ? ((ushort)(-num6)) : ((ushort)num6));
|
||||
num9++;
|
||||
ptr5++;
|
||||
ptr6++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class DifferenceEdgeDetector : BaseUsingCopyPartialFilter
|
||||
{
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public DifferenceEdgeDetector()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage source, UnmanagedImage destination, Rectangle rect)
|
||||
{
|
||||
int num = rect.Left + 1;
|
||||
int num2 = rect.Top + 1;
|
||||
int num3 = num + rect.Width - 2;
|
||||
int num4 = num2 + rect.Height - 2;
|
||||
int stride = destination.Stride;
|
||||
int stride2 = source.Stride;
|
||||
int num5 = stride - rect.Width + 2;
|
||||
int num6 = stride2 - rect.Width + 2;
|
||||
byte* ptr = (byte*)source.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destination.ImageData.ToPointer();
|
||||
ptr += stride2 * num2 + num;
|
||||
ptr2 += stride * num2 + num;
|
||||
for (int i = num2; i < num4; i++)
|
||||
{
|
||||
int num7 = num;
|
||||
while (num7 < num3)
|
||||
{
|
||||
int num8 = ptr[-stride2 - 1] - ptr[stride2 + 1];
|
||||
if (num8 < 0)
|
||||
{
|
||||
num8 = -num8;
|
||||
}
|
||||
int num9 = ptr[-stride2 + 1] - ptr[stride2 - 1];
|
||||
if (num9 < 0)
|
||||
{
|
||||
num9 = -num9;
|
||||
}
|
||||
if (num9 > num8)
|
||||
{
|
||||
num8 = num9;
|
||||
}
|
||||
num9 = ptr[-stride2] - ptr[stride2];
|
||||
if (num9 < 0)
|
||||
{
|
||||
num9 = -num9;
|
||||
}
|
||||
if (num9 > num8)
|
||||
{
|
||||
num8 = num9;
|
||||
}
|
||||
num9 = ptr[-1] - ptr[1];
|
||||
if (num9 < 0)
|
||||
{
|
||||
num9 = -num9;
|
||||
}
|
||||
if (num9 > num8)
|
||||
{
|
||||
num8 = num9;
|
||||
}
|
||||
*ptr2 = (byte)num8;
|
||||
num7++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
ptr += num6;
|
||||
ptr2 += num5;
|
||||
}
|
||||
Drawing.Rectangle(destination, rect, Color.Black);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class Dilatation : BaseUsingCopyPartialFilter
|
||||
{
|
||||
private short[,] se = new short[3, 3]
|
||||
{
|
||||
{ 1, 1, 1 },
|
||||
{ 1, 1, 1 },
|
||||
{ 1, 1, 1 }
|
||||
};
|
||||
|
||||
private int size = 3;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public Dilatation()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)1052676] = (PixelFormat)1052676;
|
||||
formatTranslations[(PixelFormat)1060876] = (PixelFormat)1060876;
|
||||
}
|
||||
|
||||
public Dilatation(short[,] se)
|
||||
: this()
|
||||
{
|
||||
int length = se.GetLength(0);
|
||||
if (length != se.GetLength(1) || length < 3 || length > 99 || length % 2 == 0)
|
||||
{
|
||||
throw new ArgumentException("Invalid size of structuring element.");
|
||||
}
|
||||
this.se = se;
|
||||
size = length;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_003c: Invalid comparison between Unknown and I4
|
||||
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_004f: Invalid comparison between Unknown and I4
|
||||
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0044: Invalid comparison between Unknown and I4
|
||||
//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_02b9: Invalid comparison between Unknown and I4
|
||||
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00a3: Invalid comparison between Unknown and I4
|
||||
//IL_030f: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0315: Invalid comparison between Unknown and I4
|
||||
PixelFormat pixelFormat = sourceData.PixelFormat;
|
||||
int left = rect.Left;
|
||||
int top = rect.Top;
|
||||
int num = left + rect.Width;
|
||||
int num2 = top + rect.Height;
|
||||
int num3 = size >> 1;
|
||||
if ((int)pixelFormat == 198659 || (int)pixelFormat == 137224)
|
||||
{
|
||||
int num4 = (((int)pixelFormat == 198659) ? 1 : 3);
|
||||
int stride = destinationData.Stride;
|
||||
int stride2 = sourceData.Stride;
|
||||
byte* ptr = (byte*)sourceData.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destinationData.ImageData.ToPointer();
|
||||
ptr += (nint)left * (nint)num4;
|
||||
ptr2 += (nint)left * (nint)num4;
|
||||
if ((int)pixelFormat == 198659)
|
||||
{
|
||||
for (int i = top; i < num2; i++)
|
||||
{
|
||||
byte* ptr3 = ptr + (nint)i * (nint)stride2;
|
||||
byte* ptr4 = ptr2 + (nint)i * (nint)stride;
|
||||
int num5 = left;
|
||||
while (num5 < num)
|
||||
{
|
||||
byte b = 0;
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
int num6 = j - num3;
|
||||
int num7 = i + num6;
|
||||
if (num7 < top)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (num7 >= num2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (int k = 0; k < size; k++)
|
||||
{
|
||||
int num8 = k - num3;
|
||||
num7 = num5 + num8;
|
||||
if (num7 >= left && num7 < num && se[j, k] == 1)
|
||||
{
|
||||
byte b2 = ptr3[num6 * stride2 + num8];
|
||||
if (b2 > b)
|
||||
{
|
||||
b = b2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*ptr4 = b;
|
||||
num5++;
|
||||
ptr3++;
|
||||
ptr4++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int l = top; l < num2; l++)
|
||||
{
|
||||
byte* ptr5 = ptr + (nint)l * (nint)stride2;
|
||||
byte* ptr6 = ptr2 + (nint)l * (nint)stride;
|
||||
int num9 = left;
|
||||
while (num9 < num)
|
||||
{
|
||||
byte b4;
|
||||
byte b5;
|
||||
byte b3 = (b4 = (b5 = 0));
|
||||
for (int m = 0; m < size; m++)
|
||||
{
|
||||
int num10 = m - num3;
|
||||
int num11 = l + num10;
|
||||
if (num11 < top)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (num11 >= num2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (int n = 0; n < size; n++)
|
||||
{
|
||||
int num12 = n - num3;
|
||||
num11 = num9 + num12;
|
||||
if (num11 >= left && num11 < num && se[m, n] == 1)
|
||||
{
|
||||
byte* ptr7 = ptr5 + (num10 * stride2 + num12 * 3);
|
||||
byte b6 = ptr7[2];
|
||||
if (b6 > b3)
|
||||
{
|
||||
b3 = b6;
|
||||
}
|
||||
b6 = ptr7[1];
|
||||
if (b6 > b4)
|
||||
{
|
||||
b4 = b6;
|
||||
}
|
||||
b6 = *ptr7;
|
||||
if (b6 > b5)
|
||||
{
|
||||
b5 = b6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ptr6[2] = b3;
|
||||
ptr6[1] = b4;
|
||||
*ptr6 = b5;
|
||||
num9++;
|
||||
ptr5 += 3;
|
||||
ptr6 += 3;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
int num13 = (((int)pixelFormat == 1052676) ? 1 : 3);
|
||||
int num14 = destinationData.Stride / 2;
|
||||
int num15 = sourceData.Stride / 2;
|
||||
ushort* ptr8 = (ushort*)sourceData.ImageData.ToPointer();
|
||||
ushort* ptr9 = (ushort*)destinationData.ImageData.ToPointer();
|
||||
ptr8 += left * num13;
|
||||
ptr9 += left * num13;
|
||||
if ((int)pixelFormat == 1052676)
|
||||
{
|
||||
for (int num16 = top; num16 < num2; num16++)
|
||||
{
|
||||
ushort* ptr10 = ptr8 + num16 * num15;
|
||||
ushort* ptr11 = ptr9 + num16 * num14;
|
||||
int num17 = left;
|
||||
while (num17 < num)
|
||||
{
|
||||
ushort num18 = 0;
|
||||
for (int num19 = 0; num19 < size; num19++)
|
||||
{
|
||||
int num20 = num19 - num3;
|
||||
int num21 = num16 + num20;
|
||||
if (num21 < top)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (num21 >= num2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (int num22 = 0; num22 < size; num22++)
|
||||
{
|
||||
int num23 = num22 - num3;
|
||||
num21 = num17 + num23;
|
||||
if (num21 >= left && num21 < num && se[num19, num22] == 1)
|
||||
{
|
||||
ushort num24 = ptr10[num20 * num15 + num23];
|
||||
if (num24 > num18)
|
||||
{
|
||||
num18 = num24;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*ptr11 = num18;
|
||||
num17++;
|
||||
ptr10++;
|
||||
ptr11++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int num25 = top; num25 < num2; num25++)
|
||||
{
|
||||
ushort* ptr12 = ptr8 + num25 * num15;
|
||||
ushort* ptr13 = ptr9 + num25 * num14;
|
||||
int num26 = left;
|
||||
while (num26 < num)
|
||||
{
|
||||
ushort num28;
|
||||
ushort num29;
|
||||
ushort num27 = (num28 = (num29 = 0));
|
||||
for (int num30 = 0; num30 < size; num30++)
|
||||
{
|
||||
int num31 = num30 - num3;
|
||||
int num32 = num25 + num31;
|
||||
if (num32 < top)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (num32 >= num2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (int num33 = 0; num33 < size; num33++)
|
||||
{
|
||||
int num34 = num33 - num3;
|
||||
num32 = num26 + num34;
|
||||
if (num32 >= left && num32 < num && se[num30, num33] == 1)
|
||||
{
|
||||
ushort* ptr14 = ptr12 + (num31 * num15 + num34 * 3);
|
||||
ushort num35 = ptr14[2];
|
||||
if (num35 > num27)
|
||||
{
|
||||
num27 = num35;
|
||||
}
|
||||
num35 = ptr14[1];
|
||||
if (num35 > num28)
|
||||
{
|
||||
num28 = num35;
|
||||
}
|
||||
num35 = *ptr14;
|
||||
if (num35 > num29)
|
||||
{
|
||||
num29 = num35;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ptr13[2] = num27;
|
||||
ptr13[1] = num28;
|
||||
*ptr13 = num29;
|
||||
num26++;
|
||||
ptr12 += 3;
|
||||
ptr13 += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class Dilatation3x3 : BaseUsingCopyPartialFilter
|
||||
{
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public Dilatation3x3()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect)
|
||||
{
|
||||
if (rect.Width < 3 || rect.Height < 3)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Processing rectangle mast be at least 3x3 in size.");
|
||||
}
|
||||
int num = rect.Left + 1;
|
||||
int num2 = rect.Top + 1;
|
||||
int num3 = rect.Right - 1;
|
||||
int num4 = rect.Bottom - 1;
|
||||
int stride = destinationData.Stride;
|
||||
int stride2 = sourceData.Stride;
|
||||
int num5 = stride - rect.Width + 1;
|
||||
int num6 = stride2 - rect.Width + 1;
|
||||
byte* ptr = (byte*)sourceData.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destinationData.ImageData.ToPointer();
|
||||
ptr += num - 1 + (num2 - 1) * stride2;
|
||||
ptr2 += num - 1 + (num2 - 1) * stride;
|
||||
byte b = *ptr;
|
||||
if (ptr[1] > b)
|
||||
{
|
||||
b = ptr[1];
|
||||
}
|
||||
if (ptr[stride2] > b)
|
||||
{
|
||||
b = ptr[stride2];
|
||||
}
|
||||
if (ptr[stride2 + 1] > b)
|
||||
{
|
||||
b = ptr[stride2 + 1];
|
||||
}
|
||||
*ptr2 = b;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
int num7 = num;
|
||||
while (num7 < num3)
|
||||
{
|
||||
b = *ptr;
|
||||
if (ptr[-1] > b)
|
||||
{
|
||||
b = ptr[-1];
|
||||
}
|
||||
if (ptr[1] > b)
|
||||
{
|
||||
b = ptr[1];
|
||||
}
|
||||
if (ptr[stride2 - 1] > b)
|
||||
{
|
||||
b = ptr[stride2 - 1];
|
||||
}
|
||||
if (ptr[stride2] > b)
|
||||
{
|
||||
b = ptr[stride2];
|
||||
}
|
||||
if (ptr[stride2 + 1] > b)
|
||||
{
|
||||
b = ptr[stride2 + 1];
|
||||
}
|
||||
*ptr2 = b;
|
||||
num7++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
b = *ptr;
|
||||
if (ptr[-1] > b)
|
||||
{
|
||||
b = ptr[-1];
|
||||
}
|
||||
if (ptr[stride2 - 1] > b)
|
||||
{
|
||||
b = ptr[stride2 - 1];
|
||||
}
|
||||
if (ptr[stride2] > b)
|
||||
{
|
||||
b = ptr[stride2];
|
||||
}
|
||||
*ptr2 = b;
|
||||
ptr += num6;
|
||||
ptr2 += num5;
|
||||
for (int i = num2; i < num4; i++)
|
||||
{
|
||||
b = *ptr;
|
||||
if (ptr[1] > b)
|
||||
{
|
||||
b = ptr[1];
|
||||
}
|
||||
if (ptr[-stride2] > b)
|
||||
{
|
||||
b = ptr[-stride2];
|
||||
}
|
||||
if (ptr[-stride2 + 1] > b)
|
||||
{
|
||||
b = ptr[-stride2 + 1];
|
||||
}
|
||||
if (ptr[stride2] > b)
|
||||
{
|
||||
b = ptr[stride2];
|
||||
}
|
||||
if (ptr[stride2 + 1] > b)
|
||||
{
|
||||
b = ptr[stride2 + 1];
|
||||
}
|
||||
*ptr2 = b;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
int num8 = num;
|
||||
while (num8 < num3)
|
||||
{
|
||||
b = *ptr;
|
||||
if (ptr[-1] > b)
|
||||
{
|
||||
b = ptr[-1];
|
||||
}
|
||||
if (ptr[1] > b)
|
||||
{
|
||||
b = ptr[1];
|
||||
}
|
||||
if (ptr[-stride2 - 1] > b)
|
||||
{
|
||||
b = ptr[-stride2 - 1];
|
||||
}
|
||||
if (ptr[-stride2] > b)
|
||||
{
|
||||
b = ptr[-stride2];
|
||||
}
|
||||
if (ptr[-stride2 + 1] > b)
|
||||
{
|
||||
b = ptr[-stride2 + 1];
|
||||
}
|
||||
if (ptr[stride2 - 1] > b)
|
||||
{
|
||||
b = ptr[stride2 - 1];
|
||||
}
|
||||
if (ptr[stride2] > b)
|
||||
{
|
||||
b = ptr[stride2];
|
||||
}
|
||||
if (ptr[stride2 + 1] > b)
|
||||
{
|
||||
b = ptr[stride2 + 1];
|
||||
}
|
||||
*ptr2 = b;
|
||||
num8++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
b = *ptr;
|
||||
if (ptr[-1] > b)
|
||||
{
|
||||
b = ptr[-1];
|
||||
}
|
||||
if (ptr[-stride2 - 1] > b)
|
||||
{
|
||||
b = ptr[-stride2 - 1];
|
||||
}
|
||||
if (ptr[-stride2] > b)
|
||||
{
|
||||
b = ptr[-stride2];
|
||||
}
|
||||
if (ptr[stride2 - 1] > b)
|
||||
{
|
||||
b = ptr[stride2 - 1];
|
||||
}
|
||||
if (ptr[stride2] > b)
|
||||
{
|
||||
b = ptr[stride2];
|
||||
}
|
||||
*ptr2 = b;
|
||||
ptr += num6;
|
||||
ptr2 += num5;
|
||||
}
|
||||
*ptr2 = (byte)(*ptr | ptr[1] | ptr[-stride2] | ptr[-stride2 + 1]);
|
||||
b = *ptr;
|
||||
if (ptr[1] > b)
|
||||
{
|
||||
b = ptr[1];
|
||||
}
|
||||
if (ptr[-stride2] > b)
|
||||
{
|
||||
b = ptr[-stride2];
|
||||
}
|
||||
if (ptr[-stride2 + 1] > b)
|
||||
{
|
||||
b = ptr[-stride2 + 1];
|
||||
}
|
||||
*ptr2 = b;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
int num9 = num;
|
||||
while (num9 < num3)
|
||||
{
|
||||
b = *ptr;
|
||||
if (ptr[-1] > b)
|
||||
{
|
||||
b = ptr[-1];
|
||||
}
|
||||
if (ptr[1] > b)
|
||||
{
|
||||
b = ptr[1];
|
||||
}
|
||||
if (ptr[-stride2 - 1] > b)
|
||||
{
|
||||
b = ptr[-stride2 - 1];
|
||||
}
|
||||
if (ptr[-stride2] > b)
|
||||
{
|
||||
b = ptr[-stride2];
|
||||
}
|
||||
if (ptr[-stride2 + 1] > b)
|
||||
{
|
||||
b = ptr[-stride2 + 1];
|
||||
}
|
||||
*ptr2 = b;
|
||||
num9++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
b = *ptr;
|
||||
if (ptr[-1] > b)
|
||||
{
|
||||
b = ptr[-1];
|
||||
}
|
||||
if (ptr[-stride2 - 1] > b)
|
||||
{
|
||||
b = ptr[-stride2 - 1];
|
||||
}
|
||||
if (ptr[-stride2] > b)
|
||||
{
|
||||
b = ptr[-stride2];
|
||||
}
|
||||
*ptr2 = b;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public sealed class Edges : Convolution
|
||||
{
|
||||
public Edges()
|
||||
: base(new int[3, 3]
|
||||
{
|
||||
{ 0, -1, 0 },
|
||||
{ -1, 4, -1 },
|
||||
{ 0, -1, 0 }
|
||||
})
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class Erosion : BaseUsingCopyPartialFilter
|
||||
{
|
||||
private short[,] se = new short[3, 3]
|
||||
{
|
||||
{ 1, 1, 1 },
|
||||
{ 1, 1, 1 },
|
||||
{ 1, 1, 1 }
|
||||
};
|
||||
|
||||
private int size = 3;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public Erosion()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)1052676] = (PixelFormat)1052676;
|
||||
formatTranslations[(PixelFormat)1060876] = (PixelFormat)1060876;
|
||||
}
|
||||
|
||||
public Erosion(short[,] se)
|
||||
: this()
|
||||
{
|
||||
int length = se.GetLength(0);
|
||||
if (length != se.GetLength(1) || length < 3 || length > 99 || length % 2 == 0)
|
||||
{
|
||||
throw new ArgumentException("Invalid size of structuring element.");
|
||||
}
|
||||
this.se = se;
|
||||
size = length;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_003c: Invalid comparison between Unknown and I4
|
||||
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_004f: Invalid comparison between Unknown and I4
|
||||
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0044: Invalid comparison between Unknown and I4
|
||||
//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_02c1: Invalid comparison between Unknown and I4
|
||||
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00a3: Invalid comparison between Unknown and I4
|
||||
//IL_0317: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_031d: Invalid comparison between Unknown and I4
|
||||
PixelFormat pixelFormat = sourceData.PixelFormat;
|
||||
int left = rect.Left;
|
||||
int top = rect.Top;
|
||||
int num = left + rect.Width;
|
||||
int num2 = top + rect.Height;
|
||||
int num3 = size >> 1;
|
||||
if ((int)pixelFormat == 198659 || (int)pixelFormat == 137224)
|
||||
{
|
||||
int num4 = (((int)pixelFormat == 198659) ? 1 : 3);
|
||||
int stride = destinationData.Stride;
|
||||
int stride2 = sourceData.Stride;
|
||||
byte* ptr = (byte*)sourceData.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destinationData.ImageData.ToPointer();
|
||||
ptr += (nint)left * (nint)num4;
|
||||
ptr2 += (nint)left * (nint)num4;
|
||||
if ((int)pixelFormat == 198659)
|
||||
{
|
||||
for (int i = top; i < num2; i++)
|
||||
{
|
||||
byte* ptr3 = ptr + (nint)i * (nint)stride2;
|
||||
byte* ptr4 = ptr2 + (nint)i * (nint)stride;
|
||||
int num5 = left;
|
||||
while (num5 < num)
|
||||
{
|
||||
byte b = byte.MaxValue;
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
int num6 = j - num3;
|
||||
int num7 = i + num6;
|
||||
if (num7 < top)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (num7 >= num2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (int k = 0; k < size; k++)
|
||||
{
|
||||
int num8 = k - num3;
|
||||
num7 = num5 + num8;
|
||||
if (num7 >= left && num7 < num && se[j, k] == 1)
|
||||
{
|
||||
byte b2 = ptr3[num6 * stride2 + num8];
|
||||
if (b2 < b)
|
||||
{
|
||||
b = b2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*ptr4 = b;
|
||||
num5++;
|
||||
ptr3++;
|
||||
ptr4++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int l = top; l < num2; l++)
|
||||
{
|
||||
byte* ptr5 = ptr + (nint)l * (nint)stride2;
|
||||
byte* ptr6 = ptr2 + (nint)l * (nint)stride;
|
||||
int num9 = left;
|
||||
while (num9 < num)
|
||||
{
|
||||
byte b4;
|
||||
byte b5;
|
||||
byte b3 = (b4 = (b5 = byte.MaxValue));
|
||||
for (int m = 0; m < size; m++)
|
||||
{
|
||||
int num10 = m - num3;
|
||||
int num11 = l + num10;
|
||||
if (num11 < top)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (num11 >= num2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (int n = 0; n < size; n++)
|
||||
{
|
||||
int num12 = n - num3;
|
||||
num11 = num9 + num12;
|
||||
if (num11 >= left && num11 < num && se[m, n] == 1)
|
||||
{
|
||||
byte* ptr7 = ptr5 + (num10 * stride2 + num12 * 3);
|
||||
byte b6 = ptr7[2];
|
||||
if (b6 < b3)
|
||||
{
|
||||
b3 = b6;
|
||||
}
|
||||
b6 = ptr7[1];
|
||||
if (b6 < b4)
|
||||
{
|
||||
b4 = b6;
|
||||
}
|
||||
b6 = *ptr7;
|
||||
if (b6 < b5)
|
||||
{
|
||||
b5 = b6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ptr6[2] = b3;
|
||||
ptr6[1] = b4;
|
||||
*ptr6 = b5;
|
||||
num9++;
|
||||
ptr5 += 3;
|
||||
ptr6 += 3;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
int num13 = (((int)pixelFormat == 1052676) ? 1 : 3);
|
||||
int num14 = destinationData.Stride / 2;
|
||||
int num15 = sourceData.Stride / 2;
|
||||
ushort* ptr8 = (ushort*)sourceData.ImageData.ToPointer();
|
||||
ushort* ptr9 = (ushort*)destinationData.ImageData.ToPointer();
|
||||
ptr8 += left * num13;
|
||||
ptr9 += left * num13;
|
||||
if ((int)pixelFormat == 1052676)
|
||||
{
|
||||
for (int num16 = top; num16 < num2; num16++)
|
||||
{
|
||||
ushort* ptr10 = ptr8 + num16 * num15;
|
||||
ushort* ptr11 = ptr9 + num16 * num14;
|
||||
int num17 = left;
|
||||
while (num17 < num)
|
||||
{
|
||||
ushort num18 = ushort.MaxValue;
|
||||
for (int num19 = 0; num19 < size; num19++)
|
||||
{
|
||||
int num20 = num19 - num3;
|
||||
int num21 = num16 + num20;
|
||||
if (num21 < top)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (num21 >= num2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (int num22 = 0; num22 < size; num22++)
|
||||
{
|
||||
int num23 = num22 - num3;
|
||||
num21 = num17 + num23;
|
||||
if (num21 >= left && num21 < num && se[num19, num22] == 1)
|
||||
{
|
||||
ushort num24 = ptr10[num20 * num15 + num23];
|
||||
if (num24 < num18)
|
||||
{
|
||||
num18 = num24;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*ptr11 = num18;
|
||||
num17++;
|
||||
ptr10++;
|
||||
ptr11++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int num25 = top; num25 < num2; num25++)
|
||||
{
|
||||
ushort* ptr12 = ptr8 + num25 * num15;
|
||||
ushort* ptr13 = ptr9 + num25 * num14;
|
||||
int num26 = left;
|
||||
while (num26 < num)
|
||||
{
|
||||
ushort num28;
|
||||
ushort num29;
|
||||
ushort num27 = (num28 = (num29 = ushort.MaxValue));
|
||||
for (int num30 = 0; num30 < size; num30++)
|
||||
{
|
||||
int num31 = num30 - num3;
|
||||
int num32 = num25 + num31;
|
||||
if (num32 < top)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (num32 >= num2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (int num33 = 0; num33 < size; num33++)
|
||||
{
|
||||
int num34 = num33 - num3;
|
||||
num32 = num26 + num34;
|
||||
if (num32 >= left && num32 < num && se[num30, num33] == 1)
|
||||
{
|
||||
ushort* ptr14 = ptr12 + (num31 * num15 + num34 * 3);
|
||||
ushort num35 = ptr14[2];
|
||||
if (num35 < num27)
|
||||
{
|
||||
num27 = num35;
|
||||
}
|
||||
num35 = ptr14[1];
|
||||
if (num35 < num28)
|
||||
{
|
||||
num28 = num35;
|
||||
}
|
||||
num35 = *ptr14;
|
||||
if (num35 < num29)
|
||||
{
|
||||
num29 = num35;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ptr13[2] = num27;
|
||||
ptr13[1] = num28;
|
||||
*ptr13 = num29;
|
||||
num26++;
|
||||
ptr12 += 3;
|
||||
ptr13 += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class Erosion3x3 : BaseUsingCopyPartialFilter
|
||||
{
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public Erosion3x3()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect)
|
||||
{
|
||||
if (rect.Width < 3 || rect.Height < 3)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Processing rectangle mast be at least 3x3 in size.");
|
||||
}
|
||||
int num = rect.Left + 1;
|
||||
int num2 = rect.Top + 1;
|
||||
int num3 = rect.Right - 1;
|
||||
int num4 = rect.Bottom - 1;
|
||||
int stride = destinationData.Stride;
|
||||
int stride2 = sourceData.Stride;
|
||||
int num5 = stride - rect.Width + 1;
|
||||
int num6 = stride2 - rect.Width + 1;
|
||||
byte* ptr = (byte*)sourceData.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destinationData.ImageData.ToPointer();
|
||||
ptr += num - 1 + (num2 - 1) * stride2;
|
||||
ptr2 += num - 1 + (num2 - 1) * stride;
|
||||
byte b = *ptr;
|
||||
if (ptr[1] < b)
|
||||
{
|
||||
b = ptr[1];
|
||||
}
|
||||
if (ptr[stride2] < b)
|
||||
{
|
||||
b = ptr[stride2];
|
||||
}
|
||||
if (ptr[stride2 + 1] < b)
|
||||
{
|
||||
b = ptr[stride2 + 1];
|
||||
}
|
||||
*ptr2 = b;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
int num7 = num;
|
||||
while (num7 < num3)
|
||||
{
|
||||
b = *ptr;
|
||||
if (ptr[-1] < b)
|
||||
{
|
||||
b = ptr[-1];
|
||||
}
|
||||
if (ptr[1] < b)
|
||||
{
|
||||
b = ptr[1];
|
||||
}
|
||||
if (ptr[stride2 - 1] < b)
|
||||
{
|
||||
b = ptr[stride2 - 1];
|
||||
}
|
||||
if (ptr[stride2] < b)
|
||||
{
|
||||
b = ptr[stride2];
|
||||
}
|
||||
if (ptr[stride2 + 1] < b)
|
||||
{
|
||||
b = ptr[stride2 + 1];
|
||||
}
|
||||
*ptr2 = b;
|
||||
num7++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
b = *ptr;
|
||||
if (ptr[-1] < b)
|
||||
{
|
||||
b = ptr[-1];
|
||||
}
|
||||
if (ptr[stride2 - 1] < b)
|
||||
{
|
||||
b = ptr[stride2 - 1];
|
||||
}
|
||||
if (ptr[stride2] < b)
|
||||
{
|
||||
b = ptr[stride2];
|
||||
}
|
||||
*ptr2 = b;
|
||||
ptr += num6;
|
||||
ptr2 += num5;
|
||||
for (int i = num2; i < num4; i++)
|
||||
{
|
||||
b = *ptr;
|
||||
if (ptr[1] < b)
|
||||
{
|
||||
b = ptr[1];
|
||||
}
|
||||
if (ptr[-stride2] < b)
|
||||
{
|
||||
b = ptr[-stride2];
|
||||
}
|
||||
if (ptr[-stride2 + 1] < b)
|
||||
{
|
||||
b = ptr[-stride2 + 1];
|
||||
}
|
||||
if (ptr[stride2] < b)
|
||||
{
|
||||
b = ptr[stride2];
|
||||
}
|
||||
if (ptr[stride2 + 1] < b)
|
||||
{
|
||||
b = ptr[stride2 + 1];
|
||||
}
|
||||
*ptr2 = b;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
int num8 = num;
|
||||
while (num8 < num3)
|
||||
{
|
||||
b = *ptr;
|
||||
if (ptr[-1] < b)
|
||||
{
|
||||
b = ptr[-1];
|
||||
}
|
||||
if (ptr[1] < b)
|
||||
{
|
||||
b = ptr[1];
|
||||
}
|
||||
if (ptr[-stride2 - 1] < b)
|
||||
{
|
||||
b = ptr[-stride2 - 1];
|
||||
}
|
||||
if (ptr[-stride2] < b)
|
||||
{
|
||||
b = ptr[-stride2];
|
||||
}
|
||||
if (ptr[-stride2 + 1] < b)
|
||||
{
|
||||
b = ptr[-stride2 + 1];
|
||||
}
|
||||
if (ptr[stride2 - 1] < b)
|
||||
{
|
||||
b = ptr[stride2 - 1];
|
||||
}
|
||||
if (ptr[stride2] < b)
|
||||
{
|
||||
b = ptr[stride2];
|
||||
}
|
||||
if (ptr[stride2 + 1] < b)
|
||||
{
|
||||
b = ptr[stride2 + 1];
|
||||
}
|
||||
*ptr2 = b;
|
||||
num8++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
b = *ptr;
|
||||
if (ptr[-1] < b)
|
||||
{
|
||||
b = ptr[-1];
|
||||
}
|
||||
if (ptr[-stride2 - 1] < b)
|
||||
{
|
||||
b = ptr[-stride2 - 1];
|
||||
}
|
||||
if (ptr[-stride2] < b)
|
||||
{
|
||||
b = ptr[-stride2];
|
||||
}
|
||||
if (ptr[stride2 - 1] < b)
|
||||
{
|
||||
b = ptr[stride2 - 1];
|
||||
}
|
||||
if (ptr[stride2] < b)
|
||||
{
|
||||
b = ptr[stride2];
|
||||
}
|
||||
*ptr2 = b;
|
||||
ptr += num6;
|
||||
ptr2 += num5;
|
||||
}
|
||||
*ptr2 = (byte)(*ptr | ptr[1] | ptr[-stride2] | ptr[-stride2 + 1]);
|
||||
b = *ptr;
|
||||
if (ptr[1] < b)
|
||||
{
|
||||
b = ptr[1];
|
||||
}
|
||||
if (ptr[-stride2] < b)
|
||||
{
|
||||
b = ptr[-stride2];
|
||||
}
|
||||
if (ptr[-stride2 + 1] < b)
|
||||
{
|
||||
b = ptr[-stride2 + 1];
|
||||
}
|
||||
*ptr2 = b;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
int num9 = num;
|
||||
while (num9 < num3)
|
||||
{
|
||||
b = *ptr;
|
||||
if (ptr[-1] < b)
|
||||
{
|
||||
b = ptr[-1];
|
||||
}
|
||||
if (ptr[1] < b)
|
||||
{
|
||||
b = ptr[1];
|
||||
}
|
||||
if (ptr[-stride2 - 1] < b)
|
||||
{
|
||||
b = ptr[-stride2 - 1];
|
||||
}
|
||||
if (ptr[-stride2] < b)
|
||||
{
|
||||
b = ptr[-stride2];
|
||||
}
|
||||
if (ptr[-stride2 + 1] < b)
|
||||
{
|
||||
b = ptr[-stride2 + 1];
|
||||
}
|
||||
*ptr2 = b;
|
||||
num9++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
b = *ptr;
|
||||
if (ptr[-1] < b)
|
||||
{
|
||||
b = ptr[-1];
|
||||
}
|
||||
if (ptr[-stride2 - 1] < b)
|
||||
{
|
||||
b = ptr[-stride2 - 1];
|
||||
}
|
||||
if (ptr[-stride2] < b)
|
||||
{
|
||||
b = ptr[-stride2];
|
||||
}
|
||||
*ptr2 = b;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public abstract class ErrorDiffusionDithering : BaseInPlacePartialFilter
|
||||
{
|
||||
private byte threshold = 128;
|
||||
|
||||
protected int x;
|
||||
|
||||
protected int y;
|
||||
|
||||
protected int startX;
|
||||
|
||||
protected int startY;
|
||||
|
||||
protected int stopX;
|
||||
|
||||
protected int stopY;
|
||||
|
||||
protected int stride;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public byte ThresholdValue
|
||||
{
|
||||
get
|
||||
{
|
||||
return threshold;
|
||||
}
|
||||
set
|
||||
{
|
||||
threshold = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
protected ErrorDiffusionDithering()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
}
|
||||
|
||||
protected unsafe abstract void Diffuse(int error, byte* ptr);
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
startX = rect.Left;
|
||||
startY = rect.Top;
|
||||
stopX = startX + rect.Width;
|
||||
stopY = startY + rect.Height;
|
||||
stride = image.Stride;
|
||||
int num = stride - rect.Width;
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
ptr += startY * stride + startX;
|
||||
for (y = startY; y < stopY; y++)
|
||||
{
|
||||
x = startX;
|
||||
while (x < stopX)
|
||||
{
|
||||
int num2 = *ptr;
|
||||
int error;
|
||||
if (num2 >= threshold)
|
||||
{
|
||||
*ptr = byte.MaxValue;
|
||||
error = num2 - 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr = 0;
|
||||
error = num2;
|
||||
}
|
||||
Diffuse(error, ptr);
|
||||
x++;
|
||||
ptr++;
|
||||
}
|
||||
ptr += num;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class ErrorDiffusionToAdjacentNeighbors : ErrorDiffusionDithering
|
||||
{
|
||||
private int[][] coefficients;
|
||||
|
||||
private int coefficientsSum;
|
||||
|
||||
public int[][] Coefficients
|
||||
{
|
||||
get
|
||||
{
|
||||
return coefficients;
|
||||
}
|
||||
set
|
||||
{
|
||||
coefficients = value;
|
||||
CalculateCoefficientsSum();
|
||||
}
|
||||
}
|
||||
|
||||
public ErrorDiffusionToAdjacentNeighbors(int[][] coefficients)
|
||||
{
|
||||
this.coefficients = coefficients;
|
||||
CalculateCoefficientsSum();
|
||||
}
|
||||
|
||||
protected unsafe override void Diffuse(int error, byte* ptr)
|
||||
{
|
||||
int[] array = coefficients[0];
|
||||
int num = 1;
|
||||
int i = 0;
|
||||
for (int num2 = array.Length; i < num2; i++)
|
||||
{
|
||||
if (x + num >= stopX)
|
||||
{
|
||||
break;
|
||||
}
|
||||
int num3 = ptr[num] + error * array[i] / coefficientsSum;
|
||||
num3 = ((num3 >= 0) ? ((num3 > 255) ? 255 : num3) : 0);
|
||||
ptr[num] = (byte)num3;
|
||||
num++;
|
||||
}
|
||||
int j = 1;
|
||||
for (int num4 = coefficients.Length; j < num4 && y + j < stopY; j++)
|
||||
{
|
||||
ptr += stride;
|
||||
array = coefficients[j];
|
||||
int k = 0;
|
||||
int num5 = array.Length;
|
||||
int num6 = -(num5 >> 1);
|
||||
for (; k < num5; k++)
|
||||
{
|
||||
if (x + num6 >= stopX)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (x + num6 >= startX)
|
||||
{
|
||||
int num3 = ptr[num6] + error * array[k] / coefficientsSum;
|
||||
num3 = ((num3 >= 0) ? ((num3 > 255) ? 255 : num3) : 0);
|
||||
ptr[num6] = (byte)num3;
|
||||
}
|
||||
num6++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateCoefficientsSum()
|
||||
{
|
||||
coefficientsSum = 0;
|
||||
int i = 0;
|
||||
for (int num = coefficients.Length; i < num; i++)
|
||||
{
|
||||
int[] array = coefficients[i];
|
||||
int j = 0;
|
||||
for (int num2 = array.Length; j < num2; j++)
|
||||
{
|
||||
coefficientsSum += array[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class EuclideanColorFiltering : BaseInPlacePartialFilter
|
||||
{
|
||||
private short radius = 100;
|
||||
|
||||
private RGB center = new RGB(byte.MaxValue, byte.MaxValue, byte.MaxValue);
|
||||
|
||||
private RGB fill = new RGB(0, 0, 0);
|
||||
|
||||
private bool fillOutside = true;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public short Radius
|
||||
{
|
||||
get
|
||||
{
|
||||
return radius;
|
||||
}
|
||||
set
|
||||
{
|
||||
radius = System.Math.Max((short)0, System.Math.Min((short)450, value));
|
||||
}
|
||||
}
|
||||
|
||||
public RGB CenterColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return center;
|
||||
}
|
||||
set
|
||||
{
|
||||
center = value;
|
||||
}
|
||||
}
|
||||
|
||||
public RGB FillColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return fill;
|
||||
}
|
||||
set
|
||||
{
|
||||
fill = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool FillOutside
|
||||
{
|
||||
get
|
||||
{
|
||||
return fillOutside;
|
||||
}
|
||||
set
|
||||
{
|
||||
fillOutside = value;
|
||||
}
|
||||
}
|
||||
|
||||
public EuclideanColorFiltering()
|
||||
{
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
}
|
||||
|
||||
public EuclideanColorFiltering(RGB center, short radius)
|
||||
: this()
|
||||
{
|
||||
this.center = center;
|
||||
this.radius = radius;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
int num = (((int)image.PixelFormat == 137224) ? 3 : 4);
|
||||
int left = rect.Left;
|
||||
int top = rect.Top;
|
||||
int num2 = left + rect.Width;
|
||||
int num3 = top + rect.Height;
|
||||
int num4 = image.Stride - rect.Width * num;
|
||||
int num5 = radius * radius;
|
||||
int red = center.Red;
|
||||
int green = center.Green;
|
||||
int blue = center.Blue;
|
||||
byte red2 = fill.Red;
|
||||
byte green2 = fill.Green;
|
||||
byte blue2 = fill.Blue;
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
ptr += top * image.Stride + left * num;
|
||||
for (int i = top; i < num3; i++)
|
||||
{
|
||||
int num6 = left;
|
||||
while (num6 < num2)
|
||||
{
|
||||
int num7 = red - ptr[2];
|
||||
int num8 = green - ptr[1];
|
||||
int num9 = blue - *ptr;
|
||||
if (num7 * num7 + num8 * num8 + num9 * num9 <= num5)
|
||||
{
|
||||
if (!fillOutside)
|
||||
{
|
||||
ptr[2] = red2;
|
||||
ptr[1] = green2;
|
||||
*ptr = blue2;
|
||||
}
|
||||
}
|
||||
else if (fillOutside)
|
||||
{
|
||||
ptr[2] = red2;
|
||||
ptr[1] = green2;
|
||||
*ptr = blue2;
|
||||
}
|
||||
num6++;
|
||||
ptr += num;
|
||||
}
|
||||
ptr += num4;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class ExtractBiggestBlob : IFilter, IFilterInformation
|
||||
{
|
||||
private Bitmap originalImage;
|
||||
|
||||
private IntPoint blobPosition;
|
||||
|
||||
public IntPoint BlobPosition => blobPosition;
|
||||
|
||||
public Dictionary<PixelFormat, PixelFormat> FormatTranslations
|
||||
{
|
||||
get
|
||||
{
|
||||
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
|
||||
Dictionary<PixelFormat, PixelFormat> dictionary = new Dictionary<PixelFormat, PixelFormat>();
|
||||
if (originalImage == null)
|
||||
{
|
||||
dictionary[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
dictionary[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
dictionary[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
dictionary[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
dictionary[(PixelFormat)925707] = (PixelFormat)925707;
|
||||
}
|
||||
else
|
||||
{
|
||||
dictionary[(PixelFormat)198659] = ((Image)originalImage).PixelFormat;
|
||||
dictionary[(PixelFormat)137224] = ((Image)originalImage).PixelFormat;
|
||||
dictionary[(PixelFormat)2498570] = ((Image)originalImage).PixelFormat;
|
||||
dictionary[(PixelFormat)139273] = ((Image)originalImage).PixelFormat;
|
||||
dictionary[(PixelFormat)925707] = ((Image)originalImage).PixelFormat;
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
}
|
||||
|
||||
public Bitmap OriginalImage
|
||||
{
|
||||
get
|
||||
{
|
||||
return originalImage;
|
||||
}
|
||||
set
|
||||
{
|
||||
originalImage = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Bitmap Apply(Bitmap image)
|
||||
{
|
||||
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)1, ((Image)image).PixelFormat);
|
||||
Bitmap val2 = null;
|
||||
try
|
||||
{
|
||||
return Apply(val);
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
}
|
||||
}
|
||||
|
||||
public Bitmap Apply(BitmapData imageData)
|
||||
{
|
||||
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00dc: Invalid comparison between Unknown and I4
|
||||
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00ee: Invalid comparison between Unknown and I4
|
||||
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0100: Invalid comparison between Unknown and I4
|
||||
//IL_0108: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0112: Invalid comparison between Unknown and I4
|
||||
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0124: Invalid comparison between Unknown and I4
|
||||
if (!FormatTranslations.ContainsKey(imageData.PixelFormat))
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Source pixel format is not supported by the filter.");
|
||||
}
|
||||
BlobCounter blobCounter = new BlobCounter(imageData);
|
||||
Blob[] objectsInformation = blobCounter.GetObjectsInformation();
|
||||
int num = 0;
|
||||
Blob blob = null;
|
||||
int i = 0;
|
||||
for (int num2 = objectsInformation.Length; i < num2; i++)
|
||||
{
|
||||
int num3 = objectsInformation[i].Rectangle.Width * objectsInformation[i].Rectangle.Height;
|
||||
if (num3 > num)
|
||||
{
|
||||
num = num3;
|
||||
blob = objectsInformation[i];
|
||||
}
|
||||
}
|
||||
if (blob == null)
|
||||
{
|
||||
throw new ArgumentException("The source image does not contain any blobs.");
|
||||
}
|
||||
blobPosition = new IntPoint(blob.Rectangle.Left, blob.Rectangle.Top);
|
||||
if (originalImage == null)
|
||||
{
|
||||
blobCounter.ExtractBlobsImage(new UnmanagedImage(imageData), blob, extractInOriginalSize: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((int)((Image)originalImage).PixelFormat != 137224 && (int)((Image)originalImage).PixelFormat != 2498570 && (int)((Image)originalImage).PixelFormat != 139273 && (int)((Image)originalImage).PixelFormat != 925707 && (int)((Image)originalImage).PixelFormat != 198659)
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Original image may be grayscale (8bpp indexed) or color (24/32bpp) image only.");
|
||||
}
|
||||
if (((Image)originalImage).Width != imageData.Width || ((Image)originalImage).Height != imageData.Height)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Original image must have the same size as passed source image.");
|
||||
}
|
||||
blobCounter.ExtractBlobsImage(originalImage, blob, extractInOriginalSize: false);
|
||||
}
|
||||
Bitmap result = blob.Image.ToManagedImage();
|
||||
blob.Image.Dispose();
|
||||
return result;
|
||||
}
|
||||
|
||||
public UnmanagedImage Apply(UnmanagedImage image)
|
||||
{
|
||||
throw new NotImplementedException("The method is not implemented for the filter.");
|
||||
}
|
||||
|
||||
public void Apply(UnmanagedImage sourceImage, UnmanagedImage destinationImage)
|
||||
{
|
||||
throw new NotImplementedException("The method is not implemented filter.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class ExtractChannel : BaseFilter
|
||||
{
|
||||
private short channel = 2;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public short Channel
|
||||
{
|
||||
get
|
||||
{
|
||||
return channel;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value != 2 && value != 1 && value != 0 && value != 3)
|
||||
{
|
||||
throw new ArgumentException("Invalid channel is specified.");
|
||||
}
|
||||
channel = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ExtractChannel()
|
||||
{
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)1060876] = (PixelFormat)1052676;
|
||||
formatTranslations[(PixelFormat)3424269] = (PixelFormat)1052676;
|
||||
}
|
||||
|
||||
public ExtractChannel(short channel)
|
||||
: this()
|
||||
{
|
||||
Channel = channel;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
|
||||
{
|
||||
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
|
||||
int width = sourceData.Width;
|
||||
int height = sourceData.Height;
|
||||
int num = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8;
|
||||
if (channel == 3 && num != 4 && num != 8)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Can not extract alpha channel from none ARGB image.");
|
||||
}
|
||||
if (num <= 4)
|
||||
{
|
||||
int num2 = sourceData.Stride - width * num;
|
||||
int num3 = destinationData.Stride - width;
|
||||
byte* ptr = (byte*)sourceData.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destinationData.ImageData.ToPointer();
|
||||
ptr += channel;
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
int num4 = 0;
|
||||
while (num4 < width)
|
||||
{
|
||||
*ptr2 = *ptr;
|
||||
num4++;
|
||||
ptr += num;
|
||||
ptr2++;
|
||||
}
|
||||
ptr += num2;
|
||||
ptr2 += num3;
|
||||
}
|
||||
return;
|
||||
}
|
||||
num /= 2;
|
||||
byte* ptr3 = (byte*)sourceData.ImageData.ToPointer();
|
||||
byte* ptr4 = (byte*)destinationData.ImageData.ToPointer();
|
||||
int stride = sourceData.Stride;
|
||||
int stride2 = destinationData.Stride;
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
ushort* ptr5 = (ushort*)(ptr3 + (nint)j * (nint)stride);
|
||||
ushort* ptr6 = (ushort*)(ptr4 + (nint)j * (nint)stride2);
|
||||
ptr5 += channel;
|
||||
int num5 = 0;
|
||||
while (num5 < width)
|
||||
{
|
||||
*ptr6 = *ptr5;
|
||||
num5++;
|
||||
ptr5 += num;
|
||||
ptr6++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class ExtractNormalizedRGBChannel : BaseFilter
|
||||
{
|
||||
private short channel = 2;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public short Channel
|
||||
{
|
||||
get
|
||||
{
|
||||
return channel;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value != 2 && value != 1 && value != 0)
|
||||
{
|
||||
throw new ArgumentException("Invalid channel is specified.");
|
||||
}
|
||||
channel = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ExtractNormalizedRGBChannel()
|
||||
{
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)1060876] = (PixelFormat)1052676;
|
||||
formatTranslations[(PixelFormat)3424269] = (PixelFormat)1052676;
|
||||
}
|
||||
|
||||
public ExtractNormalizedRGBChannel(short channel)
|
||||
: this()
|
||||
{
|
||||
Channel = channel;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
|
||||
{
|
||||
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
|
||||
int width = sourceData.Width;
|
||||
int height = sourceData.Height;
|
||||
int num = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8;
|
||||
if (num <= 4)
|
||||
{
|
||||
int num2 = sourceData.Stride - width * num;
|
||||
int num3 = destinationData.Stride - width;
|
||||
byte* ptr = (byte*)sourceData.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destinationData.ImageData.ToPointer();
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
int num4 = 0;
|
||||
while (num4 < width)
|
||||
{
|
||||
int num5 = ptr[2] + ptr[1] + *ptr;
|
||||
*ptr2 = (byte)((num5 != 0) ? ((byte)(255 * ptr[channel] / num5)) : 0);
|
||||
num4++;
|
||||
ptr += num;
|
||||
ptr2++;
|
||||
}
|
||||
ptr += num2;
|
||||
ptr2 += num3;
|
||||
}
|
||||
return;
|
||||
}
|
||||
num /= 2;
|
||||
byte* ptr3 = (byte*)sourceData.ImageData.ToPointer();
|
||||
byte* ptr4 = (byte*)destinationData.ImageData.ToPointer();
|
||||
int stride = sourceData.Stride;
|
||||
int stride2 = destinationData.Stride;
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
ushort* ptr5 = (ushort*)(ptr3 + (nint)j * (nint)stride);
|
||||
ushort* ptr6 = (ushort*)(ptr4 + (nint)j * (nint)stride2);
|
||||
int num6 = 0;
|
||||
while (num6 < width)
|
||||
{
|
||||
int num5 = ptr5[2] + ptr5[1] + *ptr5;
|
||||
*ptr6 = (ushort)((num5 != 0) ? ((ushort)(65535 * ptr5[channel] / num5)) : 0);
|
||||
num6++;
|
||||
ptr5 += num;
|
||||
ptr6++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class FillHoles : BaseInPlaceFilter
|
||||
{
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
private bool coupledSizeFiltering = true;
|
||||
|
||||
private int maxHoleWidth = int.MaxValue;
|
||||
|
||||
private int maxHoleHeight = int.MaxValue;
|
||||
|
||||
public bool CoupledSizeFiltering
|
||||
{
|
||||
get
|
||||
{
|
||||
return coupledSizeFiltering;
|
||||
}
|
||||
set
|
||||
{
|
||||
coupledSizeFiltering = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int MaxHoleWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return maxHoleWidth;
|
||||
}
|
||||
set
|
||||
{
|
||||
maxHoleWidth = System.Math.Max(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public int MaxHoleHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
return maxHoleHeight;
|
||||
}
|
||||
set
|
||||
{
|
||||
maxHoleHeight = System.Math.Max(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public FillHoles()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image)
|
||||
{
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
Invert invert = new Invert();
|
||||
UnmanagedImage image2 = invert.Apply(image);
|
||||
BlobCounter blobCounter = new BlobCounter();
|
||||
blobCounter.ProcessImage(image2);
|
||||
Blob[] objectsInformation = blobCounter.GetObjectsInformation();
|
||||
byte[] array = new byte[objectsInformation.Length + 1];
|
||||
array[0] = byte.MaxValue;
|
||||
int i = 0;
|
||||
for (int num = objectsInformation.Length; i < num; i++)
|
||||
{
|
||||
Blob blob = objectsInformation[i];
|
||||
if (blob.Rectangle.Left == 0 || blob.Rectangle.Top == 0 || blob.Rectangle.Right == width || blob.Rectangle.Bottom == height)
|
||||
{
|
||||
array[blob.ID] = 0;
|
||||
}
|
||||
else if ((coupledSizeFiltering && blob.Rectangle.Width <= maxHoleWidth && blob.Rectangle.Height <= maxHoleHeight) | (!coupledSizeFiltering && (blob.Rectangle.Width <= maxHoleWidth || blob.Rectangle.Height <= maxHoleHeight)))
|
||||
{
|
||||
array[blob.ID] = byte.MaxValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
array[blob.ID] = 0;
|
||||
}
|
||||
}
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
int num2 = image.Stride - width;
|
||||
int[] objectLabels = blobCounter.ObjectLabels;
|
||||
int j = 0;
|
||||
int num3 = 0;
|
||||
for (; j < height; j++)
|
||||
{
|
||||
int num4 = 0;
|
||||
while (num4 < width)
|
||||
{
|
||||
*ptr = array[objectLabels[num3]];
|
||||
num4++;
|
||||
num3++;
|
||||
ptr++;
|
||||
}
|
||||
ptr += num2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class FilterIterator : IFilter, IFilterInformation
|
||||
{
|
||||
private IFilter baseFilter;
|
||||
|
||||
private int iterations = 1;
|
||||
|
||||
public Dictionary<PixelFormat, PixelFormat> FormatTranslations => ((IFilterInformation)baseFilter).FormatTranslations;
|
||||
|
||||
public IFilter BaseFilter
|
||||
{
|
||||
get
|
||||
{
|
||||
return baseFilter;
|
||||
}
|
||||
set
|
||||
{
|
||||
baseFilter = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int Iterations
|
||||
{
|
||||
get
|
||||
{
|
||||
return iterations;
|
||||
}
|
||||
set
|
||||
{
|
||||
iterations = System.Math.Max(1, System.Math.Min(255, value));
|
||||
}
|
||||
}
|
||||
|
||||
public FilterIterator(IFilter baseFilter)
|
||||
{
|
||||
this.baseFilter = baseFilter;
|
||||
}
|
||||
|
||||
public FilterIterator(IFilter baseFilter, int iterations)
|
||||
{
|
||||
this.baseFilter = baseFilter;
|
||||
this.iterations = iterations;
|
||||
}
|
||||
|
||||
public Bitmap Apply(Bitmap image)
|
||||
{
|
||||
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)1, ((Image)image).PixelFormat);
|
||||
Bitmap result = Apply(val);
|
||||
image.UnlockBits(val);
|
||||
return result;
|
||||
}
|
||||
|
||||
public Bitmap Apply(BitmapData imageData)
|
||||
{
|
||||
Bitmap val = baseFilter.Apply(imageData);
|
||||
for (int i = 1; i < iterations; i++)
|
||||
{
|
||||
Bitmap val2 = val;
|
||||
val = baseFilter.Apply(val2);
|
||||
((Image)val2).Dispose();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
public UnmanagedImage Apply(UnmanagedImage image)
|
||||
{
|
||||
UnmanagedImage unmanagedImage = baseFilter.Apply(image);
|
||||
for (int i = 1; i < iterations; i++)
|
||||
{
|
||||
UnmanagedImage unmanagedImage2 = unmanagedImage;
|
||||
unmanagedImage = baseFilter.Apply(unmanagedImage2);
|
||||
unmanagedImage2.Dispose();
|
||||
}
|
||||
return unmanagedImage;
|
||||
}
|
||||
|
||||
public void Apply(UnmanagedImage sourceImage, UnmanagedImage destinationImage)
|
||||
{
|
||||
if (iterations == 1)
|
||||
{
|
||||
baseFilter.Apply(sourceImage, destinationImage);
|
||||
return;
|
||||
}
|
||||
UnmanagedImage unmanagedImage = baseFilter.Apply(sourceImage);
|
||||
iterations--;
|
||||
for (int i = 1; i < iterations; i++)
|
||||
{
|
||||
UnmanagedImage unmanagedImage2 = unmanagedImage;
|
||||
unmanagedImage = baseFilter.Apply(unmanagedImage2);
|
||||
unmanagedImage2.Dispose();
|
||||
}
|
||||
baseFilter.Apply(unmanagedImage, destinationImage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class FiltersSequence : CollectionBase, IFilter
|
||||
{
|
||||
public IFilter this[int index] => (IFilter)base.InnerList[index];
|
||||
|
||||
public FiltersSequence()
|
||||
{
|
||||
}
|
||||
|
||||
public FiltersSequence(params IFilter[] filters)
|
||||
{
|
||||
base.InnerList.AddRange(filters);
|
||||
}
|
||||
|
||||
public void Add(IFilter filter)
|
||||
{
|
||||
base.InnerList.Add(filter);
|
||||
}
|
||||
|
||||
public Bitmap Apply(Bitmap image)
|
||||
{
|
||||
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
|
||||
Bitmap val = null;
|
||||
BitmapData val2 = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)1, ((Image)image).PixelFormat);
|
||||
try
|
||||
{
|
||||
return Apply(val2);
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val2);
|
||||
}
|
||||
}
|
||||
|
||||
public Bitmap Apply(BitmapData imageData)
|
||||
{
|
||||
UnmanagedImage unmanagedImage = Apply(new UnmanagedImage(imageData));
|
||||
Bitmap result = unmanagedImage.ToManagedImage();
|
||||
unmanagedImage.Dispose();
|
||||
return result;
|
||||
}
|
||||
|
||||
public UnmanagedImage Apply(UnmanagedImage image)
|
||||
{
|
||||
int count = base.InnerList.Count;
|
||||
if (count == 0)
|
||||
{
|
||||
throw new ApplicationException("No filters in the sequence.");
|
||||
}
|
||||
UnmanagedImage unmanagedImage = null;
|
||||
UnmanagedImage unmanagedImage2 = null;
|
||||
unmanagedImage = ((IFilter)base.InnerList[0]).Apply(image);
|
||||
for (int i = 1; i < count; i++)
|
||||
{
|
||||
unmanagedImage2 = unmanagedImage;
|
||||
unmanagedImage = ((IFilter)base.InnerList[i]).Apply(unmanagedImage2);
|
||||
unmanagedImage2.Dispose();
|
||||
}
|
||||
return unmanagedImage;
|
||||
}
|
||||
|
||||
public void Apply(UnmanagedImage sourceImage, UnmanagedImage destinationImage)
|
||||
{
|
||||
int count = base.InnerList.Count;
|
||||
switch (count)
|
||||
{
|
||||
case 0:
|
||||
throw new ApplicationException("No filters in the sequence.");
|
||||
case 1:
|
||||
((IFilter)base.InnerList[0]).Apply(sourceImage, destinationImage);
|
||||
return;
|
||||
}
|
||||
UnmanagedImage unmanagedImage = null;
|
||||
UnmanagedImage unmanagedImage2 = null;
|
||||
unmanagedImage = ((IFilter)base.InnerList[0]).Apply(sourceImage);
|
||||
count--;
|
||||
for (int i = 1; i < count; i++)
|
||||
{
|
||||
unmanagedImage2 = unmanagedImage;
|
||||
unmanagedImage = ((IFilter)base.InnerList[i]).Apply(unmanagedImage2);
|
||||
unmanagedImage2.Dispose();
|
||||
}
|
||||
((IFilter)base.InnerList[count]).Apply(unmanagedImage, destinationImage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class FlatFieldCorrection : BaseInPlaceFilter
|
||||
{
|
||||
private Bitmap backgroundImage;
|
||||
|
||||
private UnmanagedImage unmanagedBackgroundImage;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public Bitmap BackgoundImage
|
||||
{
|
||||
get
|
||||
{
|
||||
return backgroundImage;
|
||||
}
|
||||
set
|
||||
{
|
||||
backgroundImage = value;
|
||||
if (value != null)
|
||||
{
|
||||
unmanagedBackgroundImage = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public UnmanagedImage UnmanagedBackgoundImage
|
||||
{
|
||||
get
|
||||
{
|
||||
return unmanagedBackgroundImage;
|
||||
}
|
||||
set
|
||||
{
|
||||
unmanagedBackgroundImage = value;
|
||||
if (value != null)
|
||||
{
|
||||
backgroundImage = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public FlatFieldCorrection()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
}
|
||||
|
||||
public FlatFieldCorrection(Bitmap backgroundImage)
|
||||
: this()
|
||||
{
|
||||
this.backgroundImage = backgroundImage;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image)
|
||||
{
|
||||
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0023: Invalid comparison between Unknown and I4
|
||||
//IL_0158: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0162: Invalid comparison between Unknown and I4
|
||||
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0112: Unknown result type (might be due to invalid IL or missing references)
|
||||
UnmanagedImage unmanagedImage = null;
|
||||
BitmapData val = null;
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
int num = image.Stride - (((int)image.PixelFormat == 198659) ? width : (width * 3));
|
||||
if (backgroundImage == null && unmanagedBackgroundImage == null)
|
||||
{
|
||||
ResizeBicubic resizeBicubic = new ResizeBicubic(width / 3, height / 3);
|
||||
UnmanagedImage unmanagedImage2 = resizeBicubic.Apply(image);
|
||||
GaussianBlur gaussianBlur = new GaussianBlur(5.0, 21);
|
||||
gaussianBlur.ApplyInPlace(unmanagedImage2);
|
||||
gaussianBlur.ApplyInPlace(unmanagedImage2);
|
||||
gaussianBlur.ApplyInPlace(unmanagedImage2);
|
||||
gaussianBlur.ApplyInPlace(unmanagedImage2);
|
||||
gaussianBlur.ApplyInPlace(unmanagedImage2);
|
||||
resizeBicubic.NewWidth = width;
|
||||
resizeBicubic.NewHeight = height;
|
||||
unmanagedImage = resizeBicubic.Apply(unmanagedImage2);
|
||||
unmanagedImage2.Dispose();
|
||||
}
|
||||
else if (backgroundImage != null)
|
||||
{
|
||||
if (width != ((Image)backgroundImage).Width || height != ((Image)backgroundImage).Height || image.PixelFormat != ((Image)backgroundImage).PixelFormat)
|
||||
{
|
||||
throw new InvalidImagePropertiesException("Source image and background images must have the same size and pixel format");
|
||||
}
|
||||
val = backgroundImage.LockBits(new Rectangle(0, 0, width, height), (ImageLockMode)1, ((Image)backgroundImage).PixelFormat);
|
||||
unmanagedImage = new UnmanagedImage(val);
|
||||
}
|
||||
else
|
||||
{
|
||||
unmanagedImage = unmanagedBackgroundImage;
|
||||
}
|
||||
ImageStatistics imageStatistics = new ImageStatistics(unmanagedImage);
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)unmanagedImage.ImageData.ToPointer();
|
||||
if ((int)image.PixelFormat == 198659)
|
||||
{
|
||||
double mean = imageStatistics.Gray.Mean;
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
int num2 = 0;
|
||||
while (num2 < width)
|
||||
{
|
||||
if (*ptr2 != 0)
|
||||
{
|
||||
*ptr = (byte)System.Math.Min(mean * (double)(int)(*ptr) / (double)(int)(*ptr2), 255.0);
|
||||
}
|
||||
num2++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
ptr += num;
|
||||
ptr2 += num;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
double mean2 = imageStatistics.Red.Mean;
|
||||
double mean3 = imageStatistics.Green.Mean;
|
||||
double mean4 = imageStatistics.Blue.Mean;
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
int num3 = 0;
|
||||
while (num3 < width)
|
||||
{
|
||||
if (ptr2[2] != 0)
|
||||
{
|
||||
ptr[2] = (byte)System.Math.Min(mean2 * (double)(int)ptr[2] / (double)(int)ptr2[2], 255.0);
|
||||
}
|
||||
if (ptr2[1] != 0)
|
||||
{
|
||||
ptr[1] = (byte)System.Math.Min(mean3 * (double)(int)ptr[1] / (double)(int)ptr2[1], 255.0);
|
||||
}
|
||||
if (*ptr2 != 0)
|
||||
{
|
||||
*ptr = (byte)System.Math.Min(mean4 * (double)(int)(*ptr) / (double)(int)(*ptr2), 255.0);
|
||||
}
|
||||
num3++;
|
||||
ptr += 3;
|
||||
ptr2 += 3;
|
||||
}
|
||||
ptr += num;
|
||||
ptr2 += num;
|
||||
}
|
||||
}
|
||||
if (backgroundImage != null)
|
||||
{
|
||||
backgroundImage.UnlockBits(val);
|
||||
}
|
||||
if (backgroundImage == null && unmanagedBackgroundImage == null)
|
||||
{
|
||||
unmanagedImage.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public sealed class FloydSteinbergDithering : ErrorDiffusionToAdjacentNeighbors
|
||||
{
|
||||
public FloydSteinbergDithering()
|
||||
: base(new int[2][]
|
||||
{
|
||||
new int[1] { 7 },
|
||||
new int[3] { 3, 5, 1 }
|
||||
})
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class GammaCorrection : BaseInPlacePartialFilter
|
||||
{
|
||||
private double gamma;
|
||||
|
||||
private byte[] table = new byte[256];
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public double Gamma
|
||||
{
|
||||
get
|
||||
{
|
||||
return gamma;
|
||||
}
|
||||
set
|
||||
{
|
||||
gamma = System.Math.Max(0.1, System.Math.Min(5.0, value));
|
||||
double y = 1.0 / gamma;
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
table[i] = (byte)System.Math.Min(255, (int)(System.Math.Pow((double)i / 255.0, y) * 255.0 + 0.5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GammaCorrection()
|
||||
: this(2.2)
|
||||
{
|
||||
}
|
||||
|
||||
public GammaCorrection(double gamma)
|
||||
{
|
||||
Gamma = gamma;
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
int num = (((int)image.PixelFormat == 198659) ? 1 : 3);
|
||||
int num2 = rect.Left * num;
|
||||
int top = rect.Top;
|
||||
int num3 = num2 + rect.Width * num;
|
||||
int num4 = top + rect.Height;
|
||||
int num5 = image.Stride - rect.Width * num;
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
ptr += top * image.Stride + num2;
|
||||
for (int i = top; i < num4; i++)
|
||||
{
|
||||
int num6 = num2;
|
||||
while (num6 < num3)
|
||||
{
|
||||
*ptr = table[*ptr];
|
||||
num6++;
|
||||
ptr++;
|
||||
}
|
||||
ptr += num5;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using AForge.Math;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public sealed class GaussianBlur : Convolution
|
||||
{
|
||||
private double sigma = 1.4;
|
||||
|
||||
private int size = 5;
|
||||
|
||||
public double Sigma
|
||||
{
|
||||
get
|
||||
{
|
||||
return sigma;
|
||||
}
|
||||
set
|
||||
{
|
||||
sigma = System.Math.Max(0.5, System.Math.Min(5.0, value));
|
||||
CreateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
public int Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return size;
|
||||
}
|
||||
set
|
||||
{
|
||||
size = System.Math.Max(3, System.Math.Min(21, value | 1));
|
||||
CreateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
public GaussianBlur()
|
||||
{
|
||||
CreateFilter();
|
||||
base.ProcessAlpha = true;
|
||||
}
|
||||
|
||||
public GaussianBlur(double sigma)
|
||||
{
|
||||
Sigma = sigma;
|
||||
base.ProcessAlpha = true;
|
||||
}
|
||||
|
||||
public GaussianBlur(double sigma, int size)
|
||||
{
|
||||
Sigma = sigma;
|
||||
Size = size;
|
||||
base.ProcessAlpha = true;
|
||||
}
|
||||
|
||||
private void CreateFilter()
|
||||
{
|
||||
Gaussian gaussian = new Gaussian(sigma);
|
||||
double[,] array = gaussian.Kernel2D(size);
|
||||
double num = array[0, 0];
|
||||
int[,] array2 = new int[size, size];
|
||||
int num2 = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
double num3 = array[i, j] / num;
|
||||
if (num3 > 65535.0)
|
||||
{
|
||||
num3 = 65535.0;
|
||||
}
|
||||
array2[i, j] = (int)num3;
|
||||
num2 += array2[i, j];
|
||||
}
|
||||
}
|
||||
base.Kernel = array2;
|
||||
base.Divisor = num2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using AForge.Math;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class GaussianSharpen : Convolution
|
||||
{
|
||||
private double sigma = 1.4;
|
||||
|
||||
private int size = 5;
|
||||
|
||||
public double Sigma
|
||||
{
|
||||
get
|
||||
{
|
||||
return sigma;
|
||||
}
|
||||
set
|
||||
{
|
||||
sigma = System.Math.Max(0.5, System.Math.Min(5.0, value));
|
||||
CreateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
public int Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return size;
|
||||
}
|
||||
set
|
||||
{
|
||||
size = System.Math.Max(3, System.Math.Min(21, value | 1));
|
||||
CreateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
public GaussianSharpen()
|
||||
{
|
||||
CreateFilter();
|
||||
}
|
||||
|
||||
public GaussianSharpen(double sigma)
|
||||
{
|
||||
Sigma = sigma;
|
||||
}
|
||||
|
||||
public GaussianSharpen(double sigma, int size)
|
||||
{
|
||||
Sigma = sigma;
|
||||
Size = size;
|
||||
}
|
||||
|
||||
private void CreateFilter()
|
||||
{
|
||||
Gaussian gaussian = new Gaussian(sigma);
|
||||
double[,] array = gaussian.Kernel2D(size);
|
||||
double num = array[0, 0];
|
||||
int[,] array2 = new int[size, size];
|
||||
int num2 = 0;
|
||||
int num3 = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
double num4 = array[i, j] / num;
|
||||
if (num4 > 65535.0)
|
||||
{
|
||||
num4 = 65535.0;
|
||||
}
|
||||
array2[i, j] = (int)num4;
|
||||
num2 += array2[i, j];
|
||||
}
|
||||
}
|
||||
int num5 = size >> 1;
|
||||
for (int k = 0; k < size; k++)
|
||||
{
|
||||
for (int l = 0; l < size; l++)
|
||||
{
|
||||
if (k == num5 && l == num5)
|
||||
{
|
||||
array2[k, l] = 2 * num2 - array2[k, l];
|
||||
}
|
||||
else
|
||||
{
|
||||
array2[k, l] = -array2[k, l];
|
||||
}
|
||||
num3 += array2[k, l];
|
||||
}
|
||||
}
|
||||
base.Kernel = array2;
|
||||
base.Divisor = num3;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class Grayscale : BaseFilter
|
||||
{
|
||||
public static class CommonAlgorithms
|
||||
{
|
||||
public static readonly Grayscale BT709 = new Grayscale(0.2125, 0.7154, 0.0721);
|
||||
|
||||
public static readonly Grayscale RMY = new Grayscale(0.5, 0.419, 0.081);
|
||||
|
||||
public static readonly Grayscale Y = new Grayscale(0.299, 0.587, 0.114);
|
||||
}
|
||||
|
||||
public readonly double RedCoefficient;
|
||||
|
||||
public readonly double GreenCoefficient;
|
||||
|
||||
public readonly double BlueCoefficient;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public Grayscale(double cr, double cg, double cb)
|
||||
{
|
||||
RedCoefficient = cr;
|
||||
GreenCoefficient = cg;
|
||||
BlueCoefficient = cb;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)1060876] = (PixelFormat)1052676;
|
||||
formatTranslations[(PixelFormat)3424269] = (PixelFormat)1052676;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
|
||||
{
|
||||
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001b: Invalid comparison between Unknown and I4
|
||||
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0036: Invalid comparison between Unknown and I4
|
||||
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0023: Invalid comparison between Unknown and I4
|
||||
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002b: Invalid comparison between Unknown and I4
|
||||
//IL_010b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0111: Invalid comparison between Unknown and I4
|
||||
int width = sourceData.Width;
|
||||
int height = sourceData.Height;
|
||||
PixelFormat pixelFormat = sourceData.PixelFormat;
|
||||
if ((int)pixelFormat == 137224 || (int)pixelFormat == 139273 || (int)pixelFormat == 2498570)
|
||||
{
|
||||
int num = (((int)pixelFormat == 137224) ? 3 : 4);
|
||||
int num2 = sourceData.Stride - width * num;
|
||||
int num3 = destinationData.Stride - width;
|
||||
int num4 = (int)(65536.0 * RedCoefficient);
|
||||
int num5 = (int)(65536.0 * GreenCoefficient);
|
||||
int num6 = (int)(65536.0 * BlueCoefficient);
|
||||
byte* ptr = (byte*)sourceData.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destinationData.ImageData.ToPointer();
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
int num7 = 0;
|
||||
while (num7 < width)
|
||||
{
|
||||
*ptr2 = (byte)(num4 * ptr[2] + num5 * ptr[1] + num6 * *ptr >> 16);
|
||||
num7++;
|
||||
ptr += num;
|
||||
ptr2++;
|
||||
}
|
||||
ptr += num2;
|
||||
ptr2 += num3;
|
||||
}
|
||||
return;
|
||||
}
|
||||
int num8 = (((int)pixelFormat == 1060876) ? 3 : 4);
|
||||
byte* ptr3 = (byte*)sourceData.ImageData.ToPointer();
|
||||
byte* ptr4 = (byte*)destinationData.ImageData.ToPointer();
|
||||
int stride = sourceData.Stride;
|
||||
int stride2 = destinationData.Stride;
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
ushort* ptr5 = (ushort*)(ptr3 + (nint)j * (nint)stride);
|
||||
ushort* ptr6 = (ushort*)(ptr4 + (nint)j * (nint)stride2);
|
||||
int num9 = 0;
|
||||
while (num9 < width)
|
||||
{
|
||||
*ptr6 = (ushort)(RedCoefficient * (double)(int)ptr5[2] + GreenCoefficient * (double)(int)ptr5[1] + BlueCoefficient * (double)(int)(*ptr5));
|
||||
num9++;
|
||||
ptr5 += num8;
|
||||
ptr6++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
[Obsolete("Use Grayscale.CommonAlgorithms.BT709 object instead")]
|
||||
public sealed class GrayscaleBT709 : Grayscale
|
||||
{
|
||||
public GrayscaleBT709()
|
||||
: base(0.2125, 0.7154, 0.0721)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
[Obsolete("Use Grayscale.CommonAlgorithms.RMY object instead")]
|
||||
public sealed class GrayscaleRMY : Grayscale
|
||||
{
|
||||
public GrayscaleRMY()
|
||||
: base(0.5, 0.419, 0.081)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public sealed class GrayscaleToRGB : BaseFilter
|
||||
{
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public GrayscaleToRGB()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)137224;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
|
||||
{
|
||||
int width = sourceData.Width;
|
||||
int height = sourceData.Height;
|
||||
int num = sourceData.Stride - width;
|
||||
int num2 = destinationData.Stride - width * 3;
|
||||
byte* ptr = (byte*)sourceData.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destinationData.ImageData.ToPointer();
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
int num3 = 0;
|
||||
while (num3 < width)
|
||||
{
|
||||
ptr2[2] = (ptr2[1] = (*ptr2 = *ptr));
|
||||
num3++;
|
||||
ptr++;
|
||||
ptr2 += 3;
|
||||
}
|
||||
ptr += num;
|
||||
ptr2 += num2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
[Obsolete("Use Grayscale.CommonAlgorithms.Y object instead")]
|
||||
public sealed class GrayscaleY : Grayscale
|
||||
{
|
||||
public GrayscaleY()
|
||||
: base(0.299, 0.587, 0.114)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class HSLFiltering : BaseInPlacePartialFilter
|
||||
{
|
||||
private IntRange hue = new IntRange(0, 359);
|
||||
|
||||
private Range saturation = new Range(0f, 1f);
|
||||
|
||||
private Range luminance = new Range(0f, 1f);
|
||||
|
||||
private int fillH;
|
||||
|
||||
private float fillS;
|
||||
|
||||
private float fillL;
|
||||
|
||||
private bool fillOutsideRange = true;
|
||||
|
||||
private bool updateH = true;
|
||||
|
||||
private bool updateS = true;
|
||||
|
||||
private bool updateL = true;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public IntRange Hue
|
||||
{
|
||||
get
|
||||
{
|
||||
return hue;
|
||||
}
|
||||
set
|
||||
{
|
||||
hue = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Range Saturation
|
||||
{
|
||||
get
|
||||
{
|
||||
return saturation;
|
||||
}
|
||||
set
|
||||
{
|
||||
saturation = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Range Luminance
|
||||
{
|
||||
get
|
||||
{
|
||||
return luminance;
|
||||
}
|
||||
set
|
||||
{
|
||||
luminance = value;
|
||||
}
|
||||
}
|
||||
|
||||
public HSL FillColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return new HSL(fillH, fillS, fillL);
|
||||
}
|
||||
set
|
||||
{
|
||||
fillH = value.Hue;
|
||||
fillS = value.Saturation;
|
||||
fillL = value.Luminance;
|
||||
}
|
||||
}
|
||||
|
||||
public bool FillOutsideRange
|
||||
{
|
||||
get
|
||||
{
|
||||
return fillOutsideRange;
|
||||
}
|
||||
set
|
||||
{
|
||||
fillOutsideRange = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool UpdateHue
|
||||
{
|
||||
get
|
||||
{
|
||||
return updateH;
|
||||
}
|
||||
set
|
||||
{
|
||||
updateH = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool UpdateSaturation
|
||||
{
|
||||
get
|
||||
{
|
||||
return updateS;
|
||||
}
|
||||
set
|
||||
{
|
||||
updateS = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool UpdateLuminance
|
||||
{
|
||||
get
|
||||
{
|
||||
return updateL;
|
||||
}
|
||||
set
|
||||
{
|
||||
updateL = value;
|
||||
}
|
||||
}
|
||||
|
||||
public HSLFiltering()
|
||||
{
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
}
|
||||
|
||||
public HSLFiltering(IntRange hue, Range saturation, Range luminance)
|
||||
: this()
|
||||
{
|
||||
this.hue = hue;
|
||||
this.saturation = saturation;
|
||||
this.luminance = luminance;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
int num = (((int)image.PixelFormat == 137224) ? 3 : 4);
|
||||
int left = rect.Left;
|
||||
int top = rect.Top;
|
||||
int num2 = left + rect.Width;
|
||||
int num3 = top + rect.Height;
|
||||
int num4 = image.Stride - rect.Width * num;
|
||||
RGB rGB = new RGB();
|
||||
HSL hSL = new HSL();
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
ptr += top * image.Stride + left * num;
|
||||
for (int i = top; i < num3; i++)
|
||||
{
|
||||
int num5 = left;
|
||||
while (num5 < num2)
|
||||
{
|
||||
bool flag = false;
|
||||
rGB.Red = ptr[2];
|
||||
rGB.Green = ptr[1];
|
||||
rGB.Blue = *ptr;
|
||||
HSL.FromRGB(rGB, hSL);
|
||||
if (hSL.Saturation >= saturation.Min && hSL.Saturation <= saturation.Max && hSL.Luminance >= luminance.Min && hSL.Luminance <= luminance.Max && ((hue.Min < hue.Max && hSL.Hue >= hue.Min && hSL.Hue <= hue.Max) || (hue.Min > hue.Max && (hSL.Hue >= hue.Min || hSL.Hue <= hue.Max))))
|
||||
{
|
||||
if (!fillOutsideRange)
|
||||
{
|
||||
if (updateH)
|
||||
{
|
||||
hSL.Hue = fillH;
|
||||
}
|
||||
if (updateS)
|
||||
{
|
||||
hSL.Saturation = fillS;
|
||||
}
|
||||
if (updateL)
|
||||
{
|
||||
hSL.Luminance = fillL;
|
||||
}
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
else if (fillOutsideRange)
|
||||
{
|
||||
if (updateH)
|
||||
{
|
||||
hSL.Hue = fillH;
|
||||
}
|
||||
if (updateS)
|
||||
{
|
||||
hSL.Saturation = fillS;
|
||||
}
|
||||
if (updateL)
|
||||
{
|
||||
hSL.Luminance = fillL;
|
||||
}
|
||||
flag = true;
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
HSL.ToRGB(hSL, rGB);
|
||||
ptr[2] = rGB.Red;
|
||||
ptr[1] = rGB.Green;
|
||||
*ptr = rGB.Blue;
|
||||
}
|
||||
num5++;
|
||||
ptr += num;
|
||||
}
|
||||
ptr += num4;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class HSLLinear : BaseInPlacePartialFilter
|
||||
{
|
||||
private Range inLuminance = new Range(0f, 1f);
|
||||
|
||||
private Range inSaturation = new Range(0f, 1f);
|
||||
|
||||
private Range outLuminance = new Range(0f, 1f);
|
||||
|
||||
private Range outSaturation = new Range(0f, 1f);
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public Range InLuminance
|
||||
{
|
||||
get
|
||||
{
|
||||
return inLuminance;
|
||||
}
|
||||
set
|
||||
{
|
||||
inLuminance = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Range OutLuminance
|
||||
{
|
||||
get
|
||||
{
|
||||
return outLuminance;
|
||||
}
|
||||
set
|
||||
{
|
||||
outLuminance = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Range InSaturation
|
||||
{
|
||||
get
|
||||
{
|
||||
return inSaturation;
|
||||
}
|
||||
set
|
||||
{
|
||||
inSaturation = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Range OutSaturation
|
||||
{
|
||||
get
|
||||
{
|
||||
return outSaturation;
|
||||
}
|
||||
set
|
||||
{
|
||||
outSaturation = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public HSLLinear()
|
||||
{
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
int num = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
int left = rect.Left;
|
||||
int top = rect.Top;
|
||||
int num2 = left + rect.Width;
|
||||
int num3 = top + rect.Height;
|
||||
int num4 = image.Stride - rect.Width * num;
|
||||
RGB rGB = new RGB();
|
||||
HSL hSL = new HSL();
|
||||
float num5 = 0f;
|
||||
float num6 = 0f;
|
||||
float num7 = 0f;
|
||||
float num8 = 0f;
|
||||
if (inLuminance.Max != inLuminance.Min)
|
||||
{
|
||||
num5 = (outLuminance.Max - outLuminance.Min) / (inLuminance.Max - inLuminance.Min);
|
||||
num6 = outLuminance.Min - num5 * inLuminance.Min;
|
||||
}
|
||||
if (inSaturation.Max != inSaturation.Min)
|
||||
{
|
||||
num7 = (outSaturation.Max - outSaturation.Min) / (inSaturation.Max - inSaturation.Min);
|
||||
num8 = outSaturation.Min - num7 * inSaturation.Min;
|
||||
}
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
ptr += top * image.Stride + left * num;
|
||||
for (int i = top; i < num3; i++)
|
||||
{
|
||||
int num9 = left;
|
||||
while (num9 < num2)
|
||||
{
|
||||
rGB.Red = ptr[2];
|
||||
rGB.Green = ptr[1];
|
||||
rGB.Blue = *ptr;
|
||||
HSL.FromRGB(rGB, hSL);
|
||||
if (hSL.Luminance >= inLuminance.Max)
|
||||
{
|
||||
hSL.Luminance = outLuminance.Max;
|
||||
}
|
||||
else if (hSL.Luminance <= inLuminance.Min)
|
||||
{
|
||||
hSL.Luminance = outLuminance.Min;
|
||||
}
|
||||
else
|
||||
{
|
||||
hSL.Luminance = num5 * hSL.Luminance + num6;
|
||||
}
|
||||
if (hSL.Saturation >= inSaturation.Max)
|
||||
{
|
||||
hSL.Saturation = outSaturation.Max;
|
||||
}
|
||||
else if (hSL.Saturation <= inSaturation.Min)
|
||||
{
|
||||
hSL.Saturation = outSaturation.Min;
|
||||
}
|
||||
else
|
||||
{
|
||||
hSL.Saturation = num7 * hSL.Saturation + num8;
|
||||
}
|
||||
HSL.ToRGB(hSL, rGB);
|
||||
ptr[2] = rGB.Red;
|
||||
ptr[1] = rGB.Green;
|
||||
*ptr = rGB.Blue;
|
||||
num9++;
|
||||
ptr += num;
|
||||
}
|
||||
ptr += num4;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class HistogramEqualization : BaseInPlacePartialFilter
|
||||
{
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public HistogramEqualization()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0018: Invalid comparison between Unknown and I4
|
||||
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0072: Invalid comparison between Unknown and I4
|
||||
int num = (((int)image.PixelFormat == 198659) ? 1 : (((int)image.PixelFormat == 137224) ? 3 : 4));
|
||||
int left = rect.Left;
|
||||
int top = rect.Top;
|
||||
int num2 = left + rect.Width;
|
||||
int num3 = top + rect.Height;
|
||||
int stride = image.Stride;
|
||||
int num4 = stride - rect.Width * num;
|
||||
int num5 = (num2 - left) * (num3 - top);
|
||||
if ((int)image.PixelFormat == 198659)
|
||||
{
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
ptr += top * stride + left;
|
||||
int[] array = new int[256];
|
||||
for (int i = top; i < num3; i++)
|
||||
{
|
||||
int num6 = left;
|
||||
while (num6 < num2)
|
||||
{
|
||||
array[*ptr]++;
|
||||
num6++;
|
||||
ptr++;
|
||||
}
|
||||
ptr += num4;
|
||||
}
|
||||
byte[] array2 = Equalize(array, num5);
|
||||
ptr = (byte*)image.ImageData.ToPointer();
|
||||
ptr += top * stride + left;
|
||||
for (int j = top; j < num3; j++)
|
||||
{
|
||||
int num7 = left;
|
||||
while (num7 < num2)
|
||||
{
|
||||
*ptr = array2[*ptr];
|
||||
num7++;
|
||||
ptr++;
|
||||
}
|
||||
ptr += num4;
|
||||
}
|
||||
return;
|
||||
}
|
||||
byte* ptr2 = (byte*)image.ImageData.ToPointer();
|
||||
ptr2 += top * stride + left * num;
|
||||
int[] array3 = new int[256];
|
||||
int[] array4 = new int[256];
|
||||
int[] array5 = new int[256];
|
||||
for (int k = top; k < num3; k++)
|
||||
{
|
||||
int num8 = left;
|
||||
while (num8 < num2)
|
||||
{
|
||||
array3[ptr2[2]]++;
|
||||
array4[ptr2[1]]++;
|
||||
array5[*ptr2]++;
|
||||
num8++;
|
||||
ptr2 += num;
|
||||
}
|
||||
ptr2 += num4;
|
||||
}
|
||||
byte[] array6 = Equalize(array3, num5);
|
||||
byte[] array7 = Equalize(array4, num5);
|
||||
byte[] array8 = Equalize(array5, num5);
|
||||
ptr2 = (byte*)image.ImageData.ToPointer();
|
||||
ptr2 += top * stride + left * num;
|
||||
for (int l = top; l < num3; l++)
|
||||
{
|
||||
int num9 = left;
|
||||
while (num9 < num2)
|
||||
{
|
||||
ptr2[2] = array6[ptr2[2]];
|
||||
ptr2[1] = array7[ptr2[1]];
|
||||
*ptr2 = array8[*ptr2];
|
||||
num9++;
|
||||
ptr2 += num;
|
||||
}
|
||||
ptr2 += num4;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] Equalize(int[] histogram, long numPixel)
|
||||
{
|
||||
byte[] array = new byte[256];
|
||||
float num = 255f / (float)numPixel;
|
||||
float num2 = (float)histogram[0] * num;
|
||||
array[0] = (byte)num2;
|
||||
for (int i = 1; i < 256; i++)
|
||||
{
|
||||
num2 += (float)histogram[i] * num;
|
||||
array[i] = (byte)num2;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class HitAndMiss : BaseUsingCopyPartialFilter
|
||||
{
|
||||
public enum Modes
|
||||
{
|
||||
HitAndMiss,
|
||||
Thinning,
|
||||
Thickening
|
||||
}
|
||||
|
||||
private short[,] se;
|
||||
|
||||
private int size;
|
||||
|
||||
private Modes mode;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public Modes Mode
|
||||
{
|
||||
get
|
||||
{
|
||||
return mode;
|
||||
}
|
||||
set
|
||||
{
|
||||
mode = value;
|
||||
}
|
||||
}
|
||||
|
||||
public HitAndMiss(short[,] se)
|
||||
{
|
||||
int length = se.GetLength(0);
|
||||
if (length != se.GetLength(1) || length < 3 || length > 99 || length % 2 == 0)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
this.se = se;
|
||||
size = length;
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
}
|
||||
|
||||
public HitAndMiss(short[,] se, Modes mode)
|
||||
: this(se)
|
||||
{
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect)
|
||||
{
|
||||
int left = rect.Left;
|
||||
int top = rect.Top;
|
||||
int num = left + rect.Width;
|
||||
int num2 = top + rect.Height;
|
||||
int stride = sourceData.Stride;
|
||||
int stride2 = destinationData.Stride;
|
||||
int num3 = stride - rect.Width;
|
||||
int num4 = stride2 - rect.Width;
|
||||
int num5 = size >> 1;
|
||||
byte[] array = new byte[3] { 255, 0, 255 };
|
||||
byte[] array2 = new byte[3];
|
||||
byte[] array3 = array2;
|
||||
int num6 = (int)mode;
|
||||
byte* ptr = (byte*)sourceData.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destinationData.ImageData.ToPointer();
|
||||
ptr += top * stride + left;
|
||||
ptr2 += top * stride2 + left;
|
||||
for (int i = top; i < num2; i++)
|
||||
{
|
||||
int num7 = left;
|
||||
while (num7 < num)
|
||||
{
|
||||
array3[1] = (array3[2] = *ptr);
|
||||
byte b = byte.MaxValue;
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
int num8 = j - num5;
|
||||
for (int k = 0; k < size; k++)
|
||||
{
|
||||
int num9 = k - num5;
|
||||
short num10 = se[j, k];
|
||||
if (num10 != -1)
|
||||
{
|
||||
if (i + num8 < top || i + num8 >= num2 || num7 + num9 < left || num7 + num9 >= num)
|
||||
{
|
||||
b = 0;
|
||||
break;
|
||||
}
|
||||
byte b2 = ptr[num8 * stride + num9];
|
||||
if ((num10 != 0 || b2 != 0) && (num10 != 1 || b2 != byte.MaxValue))
|
||||
{
|
||||
b = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (b == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
*ptr2 = ((b == byte.MaxValue) ? array[num6] : array3[num6]);
|
||||
num7++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
ptr += num3;
|
||||
ptr2 += num4;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class HomogenityEdgeDetector : BaseUsingCopyPartialFilter
|
||||
{
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public HomogenityEdgeDetector()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage source, UnmanagedImage destination, Rectangle rect)
|
||||
{
|
||||
int num = rect.Left + 1;
|
||||
int num2 = rect.Top + 1;
|
||||
int num3 = num + rect.Width - 2;
|
||||
int num4 = num2 + rect.Height - 2;
|
||||
int stride = destination.Stride;
|
||||
int stride2 = source.Stride;
|
||||
int num5 = stride - rect.Width + 2;
|
||||
int num6 = stride2 - rect.Width + 2;
|
||||
byte* ptr = (byte*)source.ImageData.ToPointer();
|
||||
byte* ptr2 = (byte*)destination.ImageData.ToPointer();
|
||||
ptr += stride2 * num2 + num;
|
||||
ptr2 += stride * num2 + num;
|
||||
for (int i = num2; i < num4; i++)
|
||||
{
|
||||
int num7 = num;
|
||||
while (num7 < num3)
|
||||
{
|
||||
int num8 = 0;
|
||||
int num9 = *ptr;
|
||||
int num10 = num9 - ptr[-stride2 - 1];
|
||||
if (num10 < 0)
|
||||
{
|
||||
num10 = -num10;
|
||||
}
|
||||
if (num10 > num8)
|
||||
{
|
||||
num8 = num10;
|
||||
}
|
||||
num10 = num9 - ptr[-stride2];
|
||||
if (num10 < 0)
|
||||
{
|
||||
num10 = -num10;
|
||||
}
|
||||
if (num10 > num8)
|
||||
{
|
||||
num8 = num10;
|
||||
}
|
||||
num10 = num9 - ptr[-stride2 + 1];
|
||||
if (num10 < 0)
|
||||
{
|
||||
num10 = -num10;
|
||||
}
|
||||
if (num10 > num8)
|
||||
{
|
||||
num8 = num10;
|
||||
}
|
||||
num10 = num9 - ptr[-1];
|
||||
if (num10 < 0)
|
||||
{
|
||||
num10 = -num10;
|
||||
}
|
||||
if (num10 > num8)
|
||||
{
|
||||
num8 = num10;
|
||||
}
|
||||
num10 = num9 - ptr[1];
|
||||
if (num10 < 0)
|
||||
{
|
||||
num10 = -num10;
|
||||
}
|
||||
if (num10 > num8)
|
||||
{
|
||||
num8 = num10;
|
||||
}
|
||||
num10 = num9 - ptr[stride2 - 1];
|
||||
if (num10 < 0)
|
||||
{
|
||||
num10 = -num10;
|
||||
}
|
||||
if (num10 > num8)
|
||||
{
|
||||
num8 = num10;
|
||||
}
|
||||
num10 = num9 - ptr[stride2];
|
||||
if (num10 < 0)
|
||||
{
|
||||
num10 = -num10;
|
||||
}
|
||||
if (num10 > num8)
|
||||
{
|
||||
num8 = num10;
|
||||
}
|
||||
num10 = num9 - ptr[stride2 + 1];
|
||||
if (num10 < 0)
|
||||
{
|
||||
num10 = -num10;
|
||||
}
|
||||
if (num10 > num8)
|
||||
{
|
||||
num8 = num10;
|
||||
}
|
||||
*ptr2 = (byte)num8;
|
||||
num7++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
ptr += num6;
|
||||
ptr2 += num5;
|
||||
}
|
||||
Drawing.Rectangle(destination, rect, Color.Black);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class HorizontalRunLengthSmoothing : BaseInPlacePartialFilter
|
||||
{
|
||||
private int maxGapSize = 10;
|
||||
|
||||
private bool processGapsWithImageBorders;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public int MaxGapSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return maxGapSize;
|
||||
}
|
||||
set
|
||||
{
|
||||
maxGapSize = System.Math.Max(1, System.Math.Min(1000, value));
|
||||
}
|
||||
}
|
||||
|
||||
public bool ProcessGapsWithImageBorders
|
||||
{
|
||||
get
|
||||
{
|
||||
return processGapsWithImageBorders;
|
||||
}
|
||||
set
|
||||
{
|
||||
processGapsWithImageBorders = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public HorizontalRunLengthSmoothing()
|
||||
{
|
||||
formatTranslations[(PixelFormat)198659] = (PixelFormat)198659;
|
||||
}
|
||||
|
||||
public HorizontalRunLengthSmoothing(int maxGapSize)
|
||||
: this()
|
||||
{
|
||||
MaxGapSize = maxGapSize;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
int top = rect.Top;
|
||||
int num = top + rect.Height;
|
||||
int width = rect.Width;
|
||||
int num2 = image.Stride - rect.Width;
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer() + (nint)top * (nint)image.Stride + rect.Left;
|
||||
for (int i = top; i < num; i++)
|
||||
{
|
||||
byte* ptr2 = ptr;
|
||||
byte* ptr3 = ptr + width;
|
||||
while (ptr < ptr3)
|
||||
{
|
||||
byte* ptr4 = ptr;
|
||||
for (; ptr < ptr3 && *ptr == 0; ptr++)
|
||||
{
|
||||
}
|
||||
if (ptr - ptr4 <= maxGapSize && (processGapsWithImageBorders || (ptr4 != ptr2 && ptr != ptr3)))
|
||||
{
|
||||
for (; ptr4 < ptr; ptr4++)
|
||||
{
|
||||
*ptr4 = byte.MaxValue;
|
||||
}
|
||||
}
|
||||
for (; ptr < ptr3 && *ptr != 0; ptr++)
|
||||
{
|
||||
}
|
||||
}
|
||||
ptr += num2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public class HueModifier : BaseInPlacePartialFilter
|
||||
{
|
||||
private int hue;
|
||||
|
||||
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
|
||||
|
||||
public override Dictionary<PixelFormat, PixelFormat> FormatTranslations => formatTranslations;
|
||||
|
||||
public int Hue
|
||||
{
|
||||
get
|
||||
{
|
||||
return hue;
|
||||
}
|
||||
set
|
||||
{
|
||||
hue = System.Math.Max(0, System.Math.Min(359, value));
|
||||
}
|
||||
}
|
||||
|
||||
public HueModifier()
|
||||
{
|
||||
formatTranslations[(PixelFormat)137224] = (PixelFormat)137224;
|
||||
formatTranslations[(PixelFormat)139273] = (PixelFormat)139273;
|
||||
formatTranslations[(PixelFormat)2498570] = (PixelFormat)2498570;
|
||||
formatTranslations[(PixelFormat)925707] = (PixelFormat)925707;
|
||||
}
|
||||
|
||||
public HueModifier(int hue)
|
||||
: this()
|
||||
{
|
||||
this.hue = hue;
|
||||
}
|
||||
|
||||
protected unsafe override void ProcessFilter(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
int num = Image.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||
int left = rect.Left;
|
||||
int top = rect.Top;
|
||||
int num2 = left + rect.Width;
|
||||
int num3 = top + rect.Height;
|
||||
int num4 = image.Stride - rect.Width * num;
|
||||
RGB rGB = new RGB();
|
||||
HSL hSL = new HSL();
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer();
|
||||
ptr += top * image.Stride + left * num;
|
||||
for (int i = top; i < num3; i++)
|
||||
{
|
||||
int num5 = left;
|
||||
while (num5 < num2)
|
||||
{
|
||||
rGB.Red = ptr[2];
|
||||
rGB.Green = ptr[1];
|
||||
rGB.Blue = *ptr;
|
||||
HSL.FromRGB(rGB, hSL);
|
||||
hSL.Hue = hue;
|
||||
HSL.ToRGB(hSL, rGB);
|
||||
ptr[2] = rGB.Red;
|
||||
ptr[1] = rGB.Green;
|
||||
*ptr = rGB.Blue;
|
||||
num5++;
|
||||
ptr += num;
|
||||
}
|
||||
ptr += num4;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging.Filters;
|
||||
|
||||
public interface IFilter
|
||||
{
|
||||
Bitmap Apply(Bitmap image);
|
||||
|
||||
Bitmap Apply(BitmapData imageData);
|
||||
|
||||
UnmanagedImage Apply(UnmanagedImage image);
|
||||
|
||||
void Apply(UnmanagedImage sourceImage, UnmanagedImage destinationImage);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user