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