BioImager  5.0.0
A .NET microscopy imaging application based on Bio library. Supports various microscopes by using imported libraries & GUI automation. Supports XInput game controllers to move stage, take images, run ImageJ macros on images or Bio C# scripts.
Loading...
Searching...
No Matches
Graphics.cs
Go to the documentation of this file.
1using AForge;
2using Bitmap = AForge.Bitmap;
3using Point = AForge.Point;
4using PointF = AForge.PointF;
5using Rectangle = AForge.Rectangle;
6using RectangleF = AForge.RectangleF;
7
8namespace BioImager.Graphics
9{
10 public struct Pen : IDisposable
11 {
12 public ColorS color;
13 public ushort width;
14 public byte bitsPerPixel;
15 public Pen(ColorS col, ushort w, int bitsPerPixel)
16 {
17 color = col;
18 width = w;
19 this.bitsPerPixel = (byte)bitsPerPixel;
20 }
21 public Pen(ColorS col, int w, int bitsPerPixel)
22 {
23 color = col;
24 width = (ushort)w;
25 this.bitsPerPixel = (byte)bitsPerPixel;
26 }
27 public void Dispose()
28 {
29 color.Dispose();
30 }
31 }
32 public class Graphics : IDisposable
33 {
34 public Bitmap buf;
35 public Pen pen;
36 private AbstractFloodFiller filler;
37 public static Graphics FromImage(Bitmap b)
38 {
39 Graphics g = new Graphics();
40 g.buf = b;
41 g.pen = new Pen(new ColorS(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue), 1, b.BitsPerPixel);
42 return g;
43 }
44 public void DrawLine(int x, int y, int x2, int y2)
45 {
46 //Bresenham's algorithm for line drawing.
47 int w = x2 - x;
48 int h = y2 - y;
49 int dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0;
50 if (w < 0) dx1 = -1; else if (w > 0) dx1 = 1;
51 if (h < 0) dy1 = -1; else if (h > 0) dy1 = 1;
52 if (w < 0) dx2 = -1; else if (w > 0) dx2 = 1;
53 int longest = Math.Abs(w);
54 int shortest = Math.Abs(h);
55 if (!(longest > shortest))
56 {
57 longest = Math.Abs(h);
58 shortest = Math.Abs(w);
59 if (h < 0) dy2 = -1; else if (h > 0) dy2 = 1;
60 dx2 = 0;
61 }
62 int numerator = longest >> 1;
63 for (int i = 0; i <= longest; i++)
64 {
65 FillEllipse(x, y, pen.width, pen.width, pen.color);
66 numerator += shortest;
67 if (!(numerator < longest))
68 {
69 numerator -= longest;
70 x += dx1;
71 y += dy1;
72 }
73 else
74 {
75 x += dx2;
76 y += dy2;
77 }
78 }
79 }
80 private void DrawLine(int x, int y, int x2, int y2, Bitmap bf, ColorS c)
81 {
82 //Bresenham's algorithm for line drawing.
83 int w = x2 - x;
84 int h = y2 - y;
85 int dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0;
86 if (w < 0) dx1 = -1; else if (w > 0) dx1 = 1;
87 if (h < 0) dy1 = -1; else if (h > 0) dy1 = 1;
88 if (w < 0) dx2 = -1; else if (w > 0) dx2 = 1;
89 int longest = Math.Abs(w);
90 int shortest = Math.Abs(h);
91 if (!(longest > shortest))
92 {
93 longest = Math.Abs(h);
94 shortest = Math.Abs(w);
95 if (h < 0) dy2 = -1; else if (h > 0) dy2 = 1;
96 dx2 = 0;
97 }
98 int numerator = longest >> 1;
99 for (int i = 0; i <= longest; i++)
100 {
101 bf.SetPixel(x, y, c);
102 numerator += shortest;
103 if (!(numerator < longest))
104 {
105 numerator -= longest;
106 x += dx1;
107 y += dy1;
108 }
109 else
110 {
111 x += dx2;
112 y += dy2;
113 }
114 }
115 }
116 public void DrawLine(PointF p, PointF p2)
117 {
118 DrawLine((int)p.X, (int)p.Y, (int)p2.X, (int)p2.Y);
119 }
120 public void FillRectangle(Rectangle r, ColorS col)
121 {
122 for (int x = r.X; x < r.Width + r.X; x++)
123 {
124 for (int y = r.Y; y < r.Height + r.Y; y++)
125 {
126 buf.SetPixel(x, y, col);
127 }
128 }
129 }
130 public void FillRectangle(RectangleF r, ColorS col)
131 {
132 FillRectangle(new Rectangle((int)Math.Ceiling(r.X), (int)Math.Ceiling(r.Y), (int)Math.Ceiling(r.Width), (int)Math.Ceiling(r.Height)), col);
133 }
135 {
136 for (int x = r.X; x < r.Width + r.X; x++)
137 {
138 for (int i = 0; i < pen.width; i++)
139 {
140 buf.SetPixel(x + i, r.Y, pen.color);
141 buf.SetPixel(x + i, r.Y + r.Height, pen.color);
142 }
143 }
144 for (int y = r.Y; y < r.Height + r.Y; y++)
145 {
146 for (int i = 0; i < pen.width; i++)
147 {
148 buf.SetPixel(r.X, y + i, pen.color);
149 buf.SetPixel(r.X + r.Width, y + i, pen.color);
150 }
151 }
152 }
154 {
155 DrawRectangle(new Rectangle((int)Math.Ceiling(r.X), (int)Math.Ceiling(r.Y), (int)Math.Ceiling(r.Width), (int)Math.Ceiling(r.Height)));
156 }
157
158 public void DrawEllipse(Rectangle r)
159 {
160 if (r.Width == 1 && r.Height == 1)
161 buf.SetPixel(r.X, r.Y, pen.color);
162 double radiusx = r.Width / 2;
163 double radiusy = r.Height / 2;
164 int x, y;
165 for (double a = 0.0; a < 360.0; a += 0.1)
166 {
167 double angle = a * System.Math.PI / 180;
168 for (int i = 0; i < pen.width; i++)
169 {
170 x = (int)(radiusx * System.Math.Cos(angle) + radiusx + r.X);
171 y = (int)(radiusy * System.Math.Sin(angle) + radiusy + r.Y);
172 buf.SetPixel(x + i, y + i, pen.color);
173 }
174 }
175 }
176 public void DrawEllipse(RectangleF r)
177 {
178 DrawEllipse(new Rectangle((int)Math.Ceiling(r.X), (int)Math.Ceiling(r.Y), (int)Math.Ceiling(r.Width), (int)Math.Ceiling(r.Height)));
179 }
180 public void FillEllipse(float xx, float yy, int w, int h, ColorS c)
181 {
182 if (w <= 1 && w <= 1)
183 {
184 buf.SetPixel((int)xx, (int)yy, c);
185 return;
186 }
187 double radiusx = w / 2;
188 double radiusy = h / 2;
189 int x, y;
190 for (double a = 90; a < 270; a += 0.1)
191 {
192 double angle = a * System.Math.PI / 180;
193 x = (int)(radiusx * System.Math.Cos(angle) + radiusx + xx);
194 y = (int)(radiusy * System.Math.Sin(angle) + radiusy + yy);
195 double angle2 = (a + 180) * System.Math.PI / 180;
196 int x2 = (int)(radiusx * System.Math.Cos(angle2) + radiusx + xx);
197 DrawScanline(x, x2, y, c);
198 }
199 }
200 public void FillEllipse(RectangleF r, ColorS c)
201 {
202 FillEllipse(new Rectangle((int)Math.Ceiling(r.X), (int)Math.Ceiling(r.Y), (int)Math.Ceiling(r.Width), (int)Math.Ceiling(r.Height)), c);
203 }
204 public void FillEllipse(Rectangle r, ColorS c)
205 {
206 FillEllipse(r.X, r.Y, r.Width, r.Height, c);
207 }
208 public void FillPolygon(PointF[] pfs, Rectangle r)
209 {
210 //We will use the flood fill algorithm to fill the polygon.
211 //First we need to create a new Buffer incase the current Buffer contains filled pixels that could prevent flood fill from filling the whole area.
212 Bitmap bf = buf.CopyInfo();
213 bf.Bytes = new byte[buf.Bytes.Length];
214
215 DrawPolygon(pfs, bf, pen.color);
216
217 filler = new QueueLinearFloodFiller(filler);
218 filler.FillColor = pen.color;
219 filler.Tolerance = new ColorS(0, 0, 0);
220 filler.Bitmap = bf;
221 //Next we need to find a point inside the polygon from where to start the flood fill.
222 //We use the center points x-line till we find a point inside.
223 Point p = new Point(r.X + (r.Width / 2), r.Y + (r.Height / 2));
224 Point? pp = null;
225 polygon = pfs;
226 for (int x = r.X; x < r.Width + r.X; x++)
227 {
228 if (PointInPolygon(x, (int)p.Y))
229 {
230 pp = new Point(x, p.Y);
231 break;
232 }
233 }
234 filler.FloodFill(pp.Value);
235 //Now that we have a filled shape we draw it onto the original bitmap
236 for (int x = 0; x < bf.SizeX; x++)
237 {
238 for (int y = 0; y < bf.SizeY; y++)
239 {
240 if (bf.GetPixel(x, y) == pen.color)
241 {
242 buf.SetPixel(x, y, pen.color);
243 }
244 }
245 }
246 bf.Dispose();
247 }
248 public void FillPolygon(PointF[] pfs, RectangleF r)
249 {
250 FillPolygon(pfs, new Rectangle((int)r.X, (int)r.Y, (int)r.Width, (int)r.Height));
251 }
252 private static PointF[] polygon;
253 public bool PointInPolygon(int x, int y)
254 {
255 int j = polygon.Length - 1;
256 bool c = false;
257 for (int i = 0; i < polygon.Length; j = i++) c ^= polygon[i].Y > y ^ polygon[j].Y > y && x < (polygon[j].X - polygon[i].X) * (y - polygon[i].Y) / (polygon[j].Y - polygon[i].Y) + polygon[i].X;
258 return c;
259 }
260
261 public void FillPolygon(PointF[] pfs, Rectangle r, ColorS c)
262 {
263 pen.color = c;
264 FillPolygon(pfs, r);
265 }
266 public void FillPolygon(PointF[] pfs, RectangleF r, ColorS c)
267 {
268 pen.color = c;
269 FillPolygon(pfs, r);
270 }
271 private void DrawPolygon(PointF[] pfs, Bitmap bf, ColorS s)
272 {
273 for (int i = 0; i < pfs.Length - 1; i++)
274 {
275 DrawLine((int)pfs[i].X, (int)pfs[i].Y, (int)pfs[i + 1].X, (int)pfs[i + 1].Y, bf, s);
276 }
277 DrawLine((int)pfs[0].X, (int)pfs[0].Y, (int)pfs[pfs.Length - 1].X, (int)pfs[pfs.Length - 1].Y, bf, s);
278 }
279 public void DrawScanline(int x, int x2, int line, ColorS col)
280 {
281 for (int xx = x; xx < x2; xx++)
282 {
283 buf.SetPixel(xx, line, col);
284 }
285 }
286 public void Dispose()
287 {
288 pen.Dispose();
289 }
290 }
291}
AForge.Bitmap Bitmap
AForge.RectangleF RectangleF
AForge.Point Point
AForge.Rectangle Rectangle
AForge.PointF PointF
System.Drawing.Graphics Graphics
Definition OMERO.cs:14
The base class that the flood fill algorithms inherit from. Implements the basic flood filler functio...
void DrawRectangle(RectangleF r)
Definition Graphics.cs:153
void DrawLine(int x, int y, int x2, int y2)
Definition Graphics.cs:44
void FillEllipse(Rectangle r, ColorS c)
Definition Graphics.cs:204
bool PointInPolygon(int x, int y)
Definition Graphics.cs:253
void DrawEllipse(Rectangle r)
Definition Graphics.cs:158
void FillRectangle(RectangleF r, ColorS col)
Definition Graphics.cs:130
void FillPolygon(PointF[] pfs, RectangleF r, ColorS c)
Definition Graphics.cs:266
void FillPolygon(PointF[] pfs, RectangleF r)
Definition Graphics.cs:248
void FillEllipse(float xx, float yy, int w, int h, ColorS c)
Definition Graphics.cs:180
void DrawLine(PointF p, PointF p2)
Definition Graphics.cs:116
void DrawRectangle(Rectangle r)
Definition Graphics.cs:134
void FillRectangle(Rectangle r, ColorS col)
Definition Graphics.cs:120
void FillPolygon(PointF[] pfs, Rectangle r)
Definition Graphics.cs:208
void DrawEllipse(RectangleF r)
Definition Graphics.cs:176
void FillPolygon(PointF[] pfs, Rectangle r, ColorS c)
Definition Graphics.cs:261
void DrawScanline(int x, int x2, int line, ColorS col)
Definition Graphics.cs:279
void FillEllipse(RectangleF r, ColorS c)
Definition Graphics.cs:200
static Graphics FromImage(Bitmap b)
Definition Graphics.cs:37
Implements the QueueLinear flood fill algorithm using array-based pixel manipulation.
Pen(ColorS col, ushort w, int bitsPerPixel)
Definition Graphics.cs:15
Pen(ColorS col, int w, int bitsPerPixel)
Definition Graphics.cs:21