using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Text; namespace ESoft.CaptchaSolver { public class Histogram { public static double MeaningCircle = 0.75; int[,] hist = new int[0, 0]; public int rlength { get { return hist.GetLength(0); } } public int plength { get { return hist.GetLength(1); } } double radius = 0; public int this[int i, int j] { get { return _ijok(i, j) ? hist[i, j] : 0; } set { if (_ijok(i, j)) hist[i, j] = value; } } public bool _ijok(int i, int j) { return i >= 0 && i < rlength && j >= 0 && j < plength; } public Histogram(int r, int rseg, int pseg) { hist = new int[rseg, pseg]; } int total = 0; public int Total { get { return total; } } private void Normalize(int maximum) { total = 0; for (int i = 0; i < rlength; i++) for (int j = 0; j < plength; j++) { if (maximum > 0) hist[i, j] = (int)Math.Floor(255.0 * (double)hist[i, j] / (double)maximum); else hist[i, j] = 0; total += hist[i, j]; } } public Histogram MakeCopy() { Histogram ret = new Histogram(10, this.rlength, this.plength); for (int i = 0; i < rlength; i++) for (int j = 0; j < plength; j++) { ret.hist[i, j] = this.hist[i, j]; } ret.radius = this.radius; ret.total = this.total; return ret; } public void Divide(int othertotal) { /*double rate = (double)(othertotal - this.total) / (double)Math.Max(this.total, othertotal); if (othertotal > 0 && rate > 0.75 && false) { int subtotal = 0; int maximum = 0; for (int i = 0; i < rlength; i++) for (int j = 0; j < plength; j++) { hist[i, j] = (int)((double)(hist[i, j]) / (double)othertotal * (double)total); maximum = Math.Max(hist[i, j], maximum); subtotal += hist[i, j]; } if (othertotal < total) Normalize(maximum); else total = subtotal; }*/ } public void CountBitImagePart(BitImage image, int x, int y, int r) { hist = new int[rlength, plength]; //clear histogram int maximum = 0; this.radius = Math.Sqrt(2) * r; for (int i = x - r; i < x + r + 1; i++) for (int j = y - r; j < y + r + 1; j++) { if (image[i, j]) { double phi = 0.0; double rad = Math.Sqrt(Math.Pow((double)(i - x), 2.0) + Math.Pow((double)(j - y), 2.0)); if ((i - x) == 0) { phi = (j - y) < 0 ? Math.PI / 2.0 : Math.PI + Math.PI / 2.0; } else if ((i - x) < 0) { phi = Math.PI + Math.Atan((double)(j - y) / (double)(i - x)); } else { phi = Math.Atan((double)(j - y) / (double)(i - x)); if (phi < 0) phi += Math.PI * 2.0; if (phi > Math.PI * 2.0) phi -= Math.PI * 2.0; } double rsegd = (rad / radius) * (double)rlength; double psegd = (phi / 2.0 / Math.PI) * (double)plength; int rseg = rsegd < 0 ? 0 : rsegd > rlength - 1 ? rlength - 1 : (int)Math.Floor(rsegd); int pseg = psegd < 0 ? 0 : psegd > plength - 1 ? plength - 1 : (int)Math.Floor(psegd); hist[rseg, pseg]++; maximum = Math.Max(hist[rseg, pseg], maximum); } } Normalize(maximum); } public void Draw(Graphics g, int x, int y, int r, bool drawlines) { for (int i = 0; i < rlength; i++) for (int j = 0; j < plength; j++) { GraphicsPath p = new GraphicsPath(); int inradius = (int)((double)i / (double)rlength * (double)r); int outradius = (int)((double)(i + 1) / (double)rlength * (double)r); int startangle = (int)((double)j / (double)plength * 360.0); int endangle = (int)((double)(j + 1) / (double)plength * 360.0); int sweepangle = (int)(360.0 / (double)plength); double startangled = (double)j / (double)plength * Math.PI * 2.0; double endangled = (double)(j + 1) / (double)plength * Math.PI * 2.0; Point outstart = new Point(x + (int)((double)outradius * Math.Cos(startangled)), y + (int)((double)outradius * Math.Sin(startangled))); Point instart = new Point(x + (int)((double)inradius * Math.Cos(startangled)), y + (int)((double)inradius * Math.Sin(startangled))); Point outend = new Point(x + (int)((double)outradius * Math.Cos(endangled)), y + (int)((double)outradius * Math.Sin(endangled))); Point inend = new Point(x + (int)((double)inradius * Math.Cos(endangled)), y + (int)((double)inradius * Math.Sin(endangled))); if (sweepangle >= 360) { p.AddEllipse(new Rectangle(x - outradius, y - outradius, outradius * 2, outradius * 2)); p.Reverse(); p.AddEllipse(new Rectangle(x - inradius, y - inradius, inradius * 2, inradius * 2)); } else { p.AddArc(new Rectangle(x - outradius, y - outradius, outradius * 2, outradius * 2), startangle, sweepangle); if (inradius > 0) { p.AddLine(outend, inend); p.AddArc(new Rectangle(x - inradius, y - inradius, inradius * 2, inradius * 2), endangle, -sweepangle); p.AddLine(instart, outstart); } else { p.AddLine(outend, new Point(x, y)); p.AddLine(new Point(x, y), outstart); } } Color c = Color.FromArgb(255 - hist[i, j], 255 - hist[i, j], 255 - hist[i, j]); g.FillPath(new SolidBrush(c), p); if(drawlines) g.DrawPath(new Pen(i < (rlength * MeaningCircle) ? Color.Black : Color.DarkGray), p); } g.DrawEllipse(new Pen(Color.Black), x - r, y - r, r * 2, r * 2); } } }