You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
322 lines
14 KiB
322 lines
14 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace GummingCommon
|
|
{
|
|
public class ImageDetectService
|
|
{
|
|
public static List<Rectangle> QueryRects(Bitmap srcBitmap, Color color, Color fillColor)
|
|
{
|
|
List<Rectangle> rects = new List<Rectangle>();
|
|
Point pt = QueryFirstPoint(srcBitmap, color);
|
|
while (pt.X > 0 || pt.Y > 0)
|
|
{
|
|
Rectangle rect = FloodFill(srcBitmap, pt, color, fillColor);
|
|
pt = QueryFirstPoint(srcBitmap, color);
|
|
if (rect.Width > 10 || rect.Height > 10)
|
|
{
|
|
rects.Add(rect);
|
|
}
|
|
}
|
|
return rects;
|
|
}
|
|
|
|
public static void FillRedPoint(Bitmap bmp)
|
|
{
|
|
System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
|
|
IntPtr ptr = bmpData.Scan0;
|
|
int stride = bmpData.Stride;
|
|
int bytes = bmpData.Stride * bmp.Height;
|
|
byte[] grayValues = new byte[bytes];
|
|
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
|
|
int _Index = 0;
|
|
for (int z = 0; z != bmp.Height; z++)
|
|
{
|
|
_Index = z * bmpData.Stride;
|
|
for (int i = 0; i != bmp.Width; i++)
|
|
{
|
|
byte b = grayValues[_Index];
|
|
byte g = grayValues[_Index + 1];
|
|
byte r = grayValues[_Index + 2];
|
|
if (b != 5 && g != 5 && r != 5)
|
|
{
|
|
grayValues[_Index] = 0;
|
|
grayValues[_Index + 1] = 0;
|
|
grayValues[_Index + 2] = 255;
|
|
}
|
|
else
|
|
{
|
|
grayValues[_Index] = 255;
|
|
grayValues[_Index + 1] = 255;
|
|
grayValues[_Index + 2] = 255;
|
|
}
|
|
_Index += 3;
|
|
}
|
|
}
|
|
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
|
|
bmp.UnlockBits(bmpData);
|
|
}
|
|
|
|
public static void FillWhiteToSpecialPoint(Bitmap bmp, byte rin, byte gin, byte bin)
|
|
{
|
|
System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
|
|
IntPtr ptr = bmpData.Scan0;
|
|
int stride = bmpData.Stride;
|
|
int bytes = bmpData.Stride * bmp.Height;
|
|
byte[] grayValues = new byte[bytes];
|
|
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
|
|
int _Index = 0;
|
|
for (int z = 0; z != bmp.Height; z++)
|
|
{
|
|
_Index = z * bmpData.Stride;
|
|
for (int i = 0; i != bmp.Width; i++)
|
|
{
|
|
byte b = grayValues[_Index];
|
|
byte g = grayValues[_Index + 1];
|
|
byte r = grayValues[_Index + 2];
|
|
if (b > 245 && g > 245 && r > 245)
|
|
{
|
|
grayValues[_Index] = rin;
|
|
grayValues[_Index + 1] = gin;
|
|
grayValues[_Index + 2] = bin;
|
|
}
|
|
_Index += 3;
|
|
}
|
|
}
|
|
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
|
|
bmp.UnlockBits(bmpData);
|
|
}
|
|
|
|
public static void FillBackgrounPoint(Bitmap bmp, Color background)
|
|
{
|
|
System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
|
|
IntPtr ptr = bmpData.Scan0;
|
|
int stride = bmpData.Stride;
|
|
int bytes = bmpData.Stride * bmp.Height;
|
|
byte[] grayValues = new byte[bytes];
|
|
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
|
|
int _Index = 0;
|
|
for (int z = 0; z != bmp.Height; z++)
|
|
{
|
|
_Index = z * bmpData.Stride;
|
|
bool jump = false;
|
|
for (int i = 0; i != bmp.Width; i++)
|
|
{
|
|
byte b = grayValues[_Index];
|
|
byte g = grayValues[_Index + 1];
|
|
byte r = grayValues[_Index + 2];
|
|
if (b < background.B && g < background.G && r < background.R)
|
|
{
|
|
if (!jump)
|
|
{
|
|
grayValues[_Index] = background.B;
|
|
grayValues[_Index + 1] = background.G;
|
|
grayValues[_Index + 2] = background.R;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!jump)
|
|
{
|
|
jump = true;
|
|
}
|
|
}
|
|
_Index += 3;
|
|
}
|
|
}
|
|
|
|
|
|
ptr = bmpData.Scan0;
|
|
_Index = 0;
|
|
for (int z = 0; z != bmp.Height; z++)
|
|
{
|
|
_Index = (z + 1) * bmpData.Stride - 3;
|
|
bool jump = false;
|
|
for (int i = bmp.Width - 1; i > -1; i--)
|
|
{
|
|
byte b = grayValues[_Index];
|
|
byte g = grayValues[_Index + 1];
|
|
byte r = grayValues[_Index + 2];
|
|
if (b < background.B && g < background.G && r < background.R)
|
|
{
|
|
if (!jump)
|
|
{
|
|
grayValues[_Index] = background.B;
|
|
grayValues[_Index + 1] = background.G;
|
|
grayValues[_Index + 2] = background.R;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!jump)
|
|
{
|
|
jump = true;
|
|
}
|
|
}
|
|
_Index -= 3;
|
|
}
|
|
}
|
|
|
|
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
|
|
bmp.UnlockBits(bmpData);
|
|
}
|
|
|
|
public static void FillRedPoint(Bitmap bmp, Color color)
|
|
{
|
|
System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
|
|
IntPtr ptr = bmpData.Scan0;
|
|
int stride = bmpData.Stride;
|
|
int bytes = bmpData.Stride * bmp.Height;
|
|
byte[] grayValues = new byte[bytes];
|
|
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
|
|
int _Index = 0;
|
|
for (int z = 0; z != bmp.Height; z++)
|
|
{
|
|
_Index = z * bmpData.Stride;
|
|
for (int i = 0; i != bmp.Width; i++)
|
|
{
|
|
byte b = grayValues[_Index];
|
|
byte g = grayValues[_Index + 1];
|
|
byte r = grayValues[_Index + 2];
|
|
if (b == color.B && g == color.G && r == color.R)
|
|
{
|
|
grayValues[_Index] = 0;
|
|
grayValues[_Index + 1] = 0;
|
|
grayValues[_Index + 2] = 255;
|
|
}
|
|
_Index += 3;
|
|
}
|
|
}
|
|
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
|
|
bmp.UnlockBits(bmpData);
|
|
}
|
|
|
|
private static Point QueryFirstPoint(Bitmap bmp, Color color)
|
|
{
|
|
Point pt = new Point(-1, -1);
|
|
System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
|
IntPtr ptr = bmpData.Scan0;
|
|
int stride = bmpData.Stride;
|
|
int bytes = bmpData.Stride * bmp.Height;
|
|
byte[] grayValues = new byte[bytes];
|
|
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
|
|
int _Index = 0;
|
|
for (int z = 0; z != bmp.Height; z++)
|
|
{
|
|
_Index = z * bmpData.Stride;
|
|
for (int i = 0; i != bmp.Width; i++)
|
|
{
|
|
byte b = grayValues[_Index];
|
|
byte g = grayValues[_Index + 1];
|
|
byte r = grayValues[_Index + 2];
|
|
if (b == color.B && g == color.G && r == color.R)
|
|
{
|
|
pt.X = i;
|
|
pt.Y = z;
|
|
break;
|
|
}
|
|
_Index += 4;
|
|
}
|
|
if (pt.X > 0)
|
|
break;
|
|
}
|
|
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
|
|
bmp.UnlockBits(bmpData);
|
|
return pt;
|
|
}
|
|
|
|
private static Rectangle FloodFill(Bitmap src, Point location, Color color, Color fillColor)
|
|
{
|
|
Rectangle rect = new Rectangle(10000, 10000, 0, 0);
|
|
int w = src.Width;
|
|
int h = src.Height;
|
|
|
|
Stack<Point> fillPoints = new Stack<Point>(w * h);
|
|
System.Drawing.Imaging.BitmapData bmpData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
|
IntPtr ptr = bmpData.Scan0;
|
|
int stride = bmpData.Stride;
|
|
int bytes = bmpData.Stride * src.Height;
|
|
byte[] grayValues = new byte[bytes];
|
|
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
|
|
byte[] temp = (byte[])grayValues.Clone();
|
|
if (location.X < 0 || location.X >= w || location.Y < 0 || location.Y >= h) throw new Exception("location error");
|
|
fillPoints.Push(new Point(location.X, location.Y));
|
|
int[,] mask = new int[w, h];
|
|
while (fillPoints.Count > 0)
|
|
{
|
|
Point p = fillPoints.Pop();
|
|
if (p.X < rect.X)
|
|
{
|
|
rect.X = p.X;
|
|
}
|
|
if (p.Y < rect.Y)
|
|
{
|
|
rect.Y = p.Y;
|
|
}
|
|
if (p.X > rect.Width)
|
|
{
|
|
rect.Width = p.X;
|
|
}
|
|
if (p.Y > rect.Height)
|
|
{
|
|
rect.Height = p.Y;
|
|
}
|
|
|
|
mask[p.X, p.Y] = 1;
|
|
temp[4 * p.X + p.Y * stride] = (byte)fillColor.B;
|
|
temp[4 * p.X + 1 + p.Y * stride] = (byte)fillColor.G;
|
|
temp[4 * p.X + 2 + p.Y * stride] = (byte)fillColor.R;
|
|
temp[4 * p.X + 3 + p.Y * stride] = (byte)fillColor.A;
|
|
|
|
if (p.X > 0 && temp[4 * (p.X - 1) + 2 + p.Y * stride] == color.R && mask[p.X - 1, p.Y] != 1)
|
|
{
|
|
temp[4 * (p.X - 1) + p.Y * stride] = (byte)fillColor.B;
|
|
temp[4 * (p.X - 1) + 1 + p.Y * stride] = (byte)fillColor.G;
|
|
temp[4 * (p.X - 1) + 2 + p.Y * stride] = (byte)fillColor.R;
|
|
temp[4 * (p.X - 1) + 3 + p.Y * stride] = (byte)fillColor.A;
|
|
fillPoints.Push(new Point(p.X - 1, p.Y));
|
|
mask[p.X - 1, p.Y] = 1;
|
|
}
|
|
if (p.X < w - 1 && temp[4 * (p.X + 1) + 2 + p.Y * stride] == color.R && mask[p.X + 1, p.Y] != 1)
|
|
{
|
|
temp[4 * (p.X + 1) + p.Y * stride] = (byte)fillColor.B;
|
|
temp[4 * (p.X + 1) + 1 + p.Y * stride] = (byte)fillColor.G;
|
|
temp[4 * (p.X + 1) + 2 + p.Y * stride] = (byte)fillColor.R;
|
|
temp[4 * (p.X + 1) + 3 + p.Y * stride] = (byte)fillColor.A;
|
|
fillPoints.Push(new Point(p.X + 1, p.Y));
|
|
mask[p.X + 1, p.Y] = 1;
|
|
}
|
|
if (p.Y > 0 && temp[4 * p.X + 2 + (p.Y - 1) * stride] == color.R && mask[p.X, p.Y - 1] != 1)
|
|
{
|
|
temp[4 * p.X + (p.Y - 1) * stride] = (byte)fillColor.B;
|
|
temp[4 * p.X + 1 + (p.Y - 1) * stride] = (byte)fillColor.G;
|
|
temp[4 * p.X + 2 + (p.Y - 1) * stride] = (byte)fillColor.R;
|
|
temp[4 * p.X + 3 + (p.Y - 1) * stride] = (byte)fillColor.A;
|
|
fillPoints.Push(new Point(p.X, p.Y - 1));
|
|
mask[p.X, p.Y - 1] = 1;
|
|
}
|
|
if (p.Y < h - 1 && temp[4 * p.X + 2 + (p.Y + 1) * stride] == color.R && mask[p.X, p.Y + 1] != 1)
|
|
{
|
|
temp[4 * p.X + (p.Y + 1) * stride] = (byte)fillColor.B;
|
|
temp[4 * p.X + 1 + (p.Y + 1) * stride] = (byte)fillColor.G;
|
|
temp[4 * p.X + 2 + (p.Y + 1) * stride] = (byte)fillColor.R;
|
|
temp[4 * p.X + 3 + (p.Y + 1) * stride] = (byte)fillColor.A;
|
|
fillPoints.Push(new Point(p.X, p.Y + 1));
|
|
mask[p.X, p.Y + 1] = 1;
|
|
}
|
|
}
|
|
fillPoints.Clear();
|
|
grayValues = (byte[])temp.Clone();
|
|
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
|
|
src.UnlockBits(bmpData);
|
|
|
|
rect.Width = rect.Width - rect.X;
|
|
rect.Height = rect.Height - rect.Y;
|
|
return rect;
|
|
}
|
|
}
|
|
}
|