Spring – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | using System; |
2 | using System.Collections.Generic; |
||
3 | using System.Drawing; |
||
4 | using System.IO; |
||
5 | using System.Reflection; |
||
6 | using System.Security.Cryptography; |
||
7 | using System.Text; |
||
8 | using System.Threading.Tasks; |
||
9 | using System.Windows.Forms; |
||
10 | |||
11 | namespace Spring.Utilities |
||
12 | { |
||
13 | public static class Helpers |
||
14 | { |
||
15 | #region Public Methods |
||
16 | |||
17 | /// <summary> |
||
18 | /// Enable double buffering for an arbitrary control. |
||
19 | /// </summary> |
||
20 | /// <param name="control">the control to enable double buffering for</param> |
||
21 | /// <returns>true on success</returns> |
||
22 | /// <remarks>Do not enable double buffering on RDP: https://devblogs.microsoft.com/oldnewthing/20060103-12/?p=32793</remarks> |
||
23 | public static bool SetDoubleBuffered(this Control control) |
||
24 | { |
||
25 | if (SystemInformation.TerminalServerSession) |
||
26 | { |
||
27 | return false; |
||
28 | } |
||
29 | |||
30 | var dgvType = control.GetType(); |
||
31 | |||
32 | var pi = dgvType.GetProperty("DoubleBuffered", |
||
33 | BindingFlags.Instance | BindingFlags.NonPublic); |
||
34 | |||
35 | if (pi == null) |
||
36 | { |
||
37 | return false; |
||
38 | } |
||
39 | |||
40 | pi.SetValue(control, true, null); |
||
41 | |||
42 | return true; |
||
43 | } |
||
44 | |||
45 | /// <summary> |
||
46 | /// Crop whitespace around a bitmap. |
||
47 | /// </summary> |
||
48 | /// <param name="bmp">the bitmap to process</param> |
||
49 | /// <returns>a cropped bitmap</returns> |
||
50 | /// <remarks>https://stackoverflow.com/users/329367/darren</remarks> |
||
51 | public static Bitmap Crop(Bitmap bmp) |
||
52 | { |
||
53 | var w = bmp.Width; |
||
54 | var h = bmp.Height; |
||
55 | |||
56 | bool AllWhiteRow(int row) |
||
57 | { |
||
58 | for (var i = 0; i < w; ++i) |
||
59 | { |
||
60 | if (bmp.GetPixel(i, row) |
||
61 | .R != |
||
62 | 255) |
||
63 | { |
||
64 | return false; |
||
65 | } |
||
66 | } |
||
67 | |||
68 | return true; |
||
69 | } |
||
70 | |||
71 | bool AllWhiteColumn(int col) |
||
72 | { |
||
73 | for (var i = 0; i < h; ++i) |
||
74 | { |
||
75 | if (bmp.GetPixel(col, i) |
||
76 | .R != |
||
77 | 255) |
||
78 | { |
||
79 | return false; |
||
80 | } |
||
81 | } |
||
82 | |||
83 | return true; |
||
84 | } |
||
85 | |||
86 | var topmost = 0; |
||
87 | |||
88 | for (var row = 0; row < h; ++row) |
||
89 | { |
||
90 | if (AllWhiteRow(row)) |
||
91 | { |
||
92 | topmost = row; |
||
93 | } |
||
94 | else |
||
95 | { |
||
96 | break; |
||
97 | } |
||
98 | } |
||
99 | |||
100 | var bottommost = 0; |
||
101 | |||
102 | for (var row = h - 1; row >= 0; --row) |
||
103 | { |
||
104 | if (AllWhiteRow(row)) |
||
105 | { |
||
106 | bottommost = row; |
||
107 | } |
||
108 | else |
||
109 | { |
||
110 | break; |
||
111 | } |
||
112 | } |
||
113 | |||
114 | int leftmost = 0, rightmost = 0; |
||
115 | |||
116 | for (var col = 0; col < w; ++col) |
||
117 | { |
||
118 | if (AllWhiteColumn(col)) |
||
119 | { |
||
120 | leftmost = col; |
||
121 | } |
||
122 | else |
||
123 | { |
||
124 | break; |
||
125 | } |
||
126 | } |
||
127 | |||
128 | for (var col = w - 1; col >= 0; --col) |
||
129 | { |
||
130 | if (AllWhiteColumn(col)) |
||
131 | { |
||
132 | rightmost = col; |
||
133 | } |
||
134 | else |
||
135 | { |
||
136 | break; |
||
137 | } |
||
138 | } |
||
139 | |||
140 | if (rightmost == 0) |
||
141 | { |
||
142 | rightmost = w; // As reached left |
||
143 | } |
||
144 | |||
145 | if (bottommost == 0) |
||
146 | { |
||
147 | bottommost = h; // As reached top. |
||
148 | } |
||
149 | |||
150 | var croppedWidth = rightmost - leftmost; |
||
151 | var croppedHeight = bottommost - topmost; |
||
152 | |||
153 | if (croppedWidth == 0) // No border on left or right |
||
154 | { |
||
155 | leftmost = 0; |
||
156 | croppedWidth = w; |
||
157 | } |
||
158 | |||
159 | if (croppedHeight == 0) // No border on top or bottom |
||
160 | { |
||
161 | topmost = 0; |
||
162 | croppedHeight = h; |
||
163 | } |
||
164 | |||
165 | try |
||
166 | { |
||
167 | var target = new Bitmap(croppedWidth, croppedHeight); |
||
168 | |||
169 | using (var g = Graphics.FromImage(target)) |
||
170 | { |
||
171 | g.DrawImage(bmp, |
||
172 | new RectangleF(0, 0, croppedWidth, croppedHeight), |
||
173 | new RectangleF(leftmost, topmost, croppedWidth, croppedHeight), |
||
174 | GraphicsUnit.Pixel); |
||
175 | } |
||
176 | |||
177 | return target; |
||
178 | } |
||
179 | catch (Exception ex) |
||
180 | { |
||
181 | throw new Exception( |
||
182 | $"Values are topmost={topmost} btm={bottommost} left={leftmost} right={rightmost} croppedWidth={croppedWidth} croppedHeight={croppedHeight}", |
||
183 | ex); |
||
184 | } |
||
185 | } |
||
186 | |||
187 | public static string Md5Hash(string input) |
||
188 | { |
||
189 | // Use input string to calculate MD5 hash |
||
190 | using (var md5 = MD5.Create()) |
||
191 | { |
||
192 | var inputBytes = Encoding.ASCII.GetBytes(input); |
||
193 | var hashBytes = md5.ComputeHash(inputBytes); |
||
194 | |||
195 | // Convert the byte array to hexadecimal string |
||
196 | var sb = new StringBuilder(); |
||
197 | |||
198 | foreach (var hashByte in hashBytes) |
||
199 | { |
||
200 | sb.Append(hashByte.ToString("X2")); |
||
201 | } |
||
202 | |||
203 | return sb.ToString(); |
||
204 | } |
||
205 | } |
||
206 | |||
207 | public static string Sha1Hash(string input) |
||
208 | { |
||
209 | using (var sha1 = new SHA1Managed()) |
||
210 | { |
||
211 | var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(input)); |
||
212 | var sb = new StringBuilder(hash.Length * 2); |
||
213 | |||
214 | foreach (var b in hash) |
||
215 | { |
||
216 | // can be "x2" if you want lowercase |
||
217 | sb.Append(b.ToString("X2")); |
||
218 | } |
||
219 | |||
220 | return sb.ToString(); |
||
221 | } |
||
222 | } |
||
223 | |||
224 | public static async Task<byte[]> LoadResource(string resource) |
||
225 | { |
||
226 | var assembly = Assembly.GetExecutingAssembly(); |
||
227 | |||
228 | using (var manifestResourceStream = assembly.GetManifestResourceStream(resource)) |
||
229 | { |
||
230 | if (manifestResourceStream == null) |
||
231 | { |
||
232 | return null; |
||
233 | } |
||
234 | |||
235 | var memoryStream = new MemoryStream(); |
||
236 | |||
237 | await manifestResourceStream.CopyToAsync(memoryStream); |
||
238 | |||
239 | memoryStream.Position = 0L; |
||
240 | |||
241 | return memoryStream.ToArray(); |
||
242 | } |
||
243 | } |
||
244 | |||
245 | public static void InvokeIfRequired<T>(this T control, Action<T> action) where T : Control |
||
246 | { |
||
247 | if (control.InvokeRequired) |
||
248 | { |
||
249 | control.BeginInvoke((MethodInvoker) delegate { action(control); }); |
||
250 | |||
251 | return; |
||
252 | } |
||
253 | |||
254 | action(control); |
||
255 | } |
||
256 | |||
257 | public static T MapValueToRange<T>(this T value, T xMin, T xMax, T yMin, T yMax) |
||
258 | where T : struct, IComparable<T>, IConvertible => |
||
259 | (dynamic) yMin + |
||
260 | ((dynamic) yMax - (dynamic) yMin) * ((dynamic) value - (dynamic) xMin) / ((dynamic) xMax - (dynamic) xMin); |
||
261 | |||
262 | public static IEnumerable<TU> SequenceSubtract<TU, TV>(this IEnumerable<TU> a, |
||
263 | IEnumerable<TV> b, |
||
264 | Func<TU, TV, bool> cmp) |
||
265 | { |
||
266 | var eb = new List<TV>(b); |
||
267 | |||
268 | using (var ea = a.GetEnumerator()) |
||
269 | { |
||
270 | while (ea.MoveNext()) |
||
271 | { |
||
272 | if (ea.Current == null) |
||
273 | { |
||
274 | continue; |
||
275 | } |
||
276 | |||
277 | foreach (var ib in eb) |
||
278 | { |
||
279 | if (cmp.Invoke(ea.Current, ib)) |
||
280 | { |
||
281 | continue; |
||
282 | } |
||
283 | |||
284 | yield return ea.Current; |
||
285 | |||
286 | break; |
||
287 | } |
||
288 | } |
||
289 | } |
||
290 | } |
||
291 | |||
292 | #endregion |
||
293 | } |
||
294 | } |