1010using System . Threading . Tasks ;
1111using AngleSharp . Html . Dom ;
1212using AngleSharp . Html . Parser ;
13+ using JetBrains . Annotations ;
1314using Novus . Win32 ;
1415using SimpleCore . Net ;
1516using SimpleCore . Utilities ;
@@ -150,6 +151,24 @@ public static Dictionary<string, string> UtilitiesMap
150151 #endregion
151152
152153
154+ public static Image GetImage ( string s )
155+ {
156+ // TODO: Using Image objects creates a memory leak; disposing them doesn't fix anything either (?)
157+
158+ using var wc = new WebClient ( ) ;
159+
160+ byte [ ] buf = wc . DownloadData ( s ) ;
161+
162+ var stream = new MemoryStream ( buf ) ;
163+
164+ Debug . WriteLine ( $ "Alloc { buf . Length } ") ;
165+
166+ var image = Image . FromStream ( stream ) ;
167+
168+ return image ;
169+ }
170+
171+
153172 /// <summary>
154173 /// Scans for direct images within a webpage.
155174 /// </summary>
@@ -160,12 +179,12 @@ public static Dictionary<string, string> UtilitiesMap
160179 /// <param name="readImage">Whether to read image metadata</param>
161180 /// <param name="imageFilter">Filter criteria for images (applicable iff <paramref name="readImage"/> is <c>true</c>)</param>
162181 public static List < DirectImage > FindDirectImages ( string url , DirectImageType directType = DirectImageType . Regex ,
163- int count = 5 , double pingTimeSec = 1 ,
164- bool readImage = true , Predicate < Image > imageFilter = null )
182+ int count = 5 , double pingTimeSec = 1 , bool readImage = true ,
183+ Predicate < Image > imageFilter = null )
165184 {
166- var directImages = new List < DirectImage > ( ) ;
185+ var images = new List < DirectImage > ( ) ;
167186
168- /* string gallerydl = UtilitiesMap[GALLERY_DL_EXE];
187+ string gallerydl = UtilitiesMap [ GALLERY_DL_EXE ] ;
169188
170189 if ( gallerydl != null ) {
171190
@@ -188,56 +207,57 @@ public static List<DirectImage> FindDirectImages(string url, DirectImageType dir
188207 var standardOutput = output . StandardOutput ;
189208
190209 while ( ! standardOutput . EndOfStream ) {
191- string str = standardOutput.ReadLine().Trim().Trim('|');
210+ string str = standardOutput . ReadLine ( )
211+ . Split ( '|' )
212+ . First ( ) ;
192213
193- directImages.Add( new DirectImage
214+ var di = new DirectImage
194215 {
195216 Direct = new Uri ( str ) ,
196- Image = Image.FromStream(WebUtilities.GetStream(str))
197- });
198- //Debug.WriteLine($">>{d}");
217+ } ;
218+
219+ if ( readImage ) {
220+ di . Image = GetImage ( str ) ;
221+ }
222+
223+ images . Add ( di ) ;
199224 }
200225
201226 var standardError = output . StandardError ;
202227
203228 while ( ! standardError . EndOfStream ) {
204- var line = standardError.ReadLine();
205- Debug.WriteLine($"{GALLERY_DL_EXE}: {line}", C_ERROR);
229+ string line = standardError . ReadLine ( ) ;
206230
207- if (line!= null) {
231+ if ( line != null ) {
208232 goto manual ;
209233 }
210234 }
211235
212236
213-
214- return directImages.OrderByDescending(x => x.Image.Width * x.Image.Height).ToList();
237+ goto ret ;
215238 }
216239
217- manual:*/
218-
219- var sw = Stopwatch . StartNew ( ) ;
240+ manual :
220241
221242 imageFilter ??= ( x ) => true ;
222243
223244 var pingTime = TimeSpan . FromSeconds ( pingTimeSec ) ;
224245
225-
226246 IHtmlDocument document ;
227247
228248 try {
229249 string html = WebUtilities . GetString ( url ) ;
230250 var parser = new HtmlParser ( ) ;
231251
232252 document = parser . ParseDocument ( html ) ;
253+
233254 }
234255 catch ( Exception e ) {
235256 Debug . WriteLine ( $ "{ e . Message } ") ;
236257
237258 return null ;
238259 }
239260
240-
241261 var cts = new CancellationTokenSource ( ) ;
242262
243263 var flat = new List < string > ( ) ;
@@ -247,77 +267,69 @@ public static List<DirectImage> FindDirectImages(string url, DirectImageType dir
247267
248268 flat = flat . Distinct ( ) . ToList ( ) ;
249269
250- //var fragments = flat.Chunk(fragmentSize).ToArray();
251-
252- //var tasks = new List<Task>();
253-
254- //count = Math.Clamp(count, count, flat.Count);
255- var act = new List < Action > ( ) ;
256-
257- for ( int i = 0 ; i < flat . Count ; i ++ ) {
258-
259- int iCopy = i ;
270+ var options = new ParallelOptions
271+ {
272+ MaxDegreeOfParallelism = Int32 . MaxValue ,
273+ TaskScheduler = TaskScheduler . Default ,
274+ CancellationToken = cts . Token
275+ } ;
260276
261- var imagesCopy = directImages ;
277+ var imagesCopy = images ;
262278
263- void Function ( )
264- {
265- string currentUrl = flat [ iCopy ] ;
266-
267- if ( directImages . Count >= count ) {
268- return ;
269- }
279+ Parallel . For ( 0 , flat . Count , options , i =>
280+ {
281+ string currentUrl = flat [ i ] ;
270282
271- if ( ! Network . IsUri ( currentUrl , out var uri ) )
272- return ;
283+ if ( imagesCopy . Count >= count ) {
284+ return ;
285+ }
273286
274- if ( ! Network . IsAlive ( uri , ( long ) pingTime . TotalMilliseconds ) )
275- return ;
287+ if ( ! Network . IsUri ( currentUrl , out var uri ) )
288+ return ;
276289
277- if ( ! IsDirect ( currentUrl , directType ) )
278- return ;
290+ if ( ! Network . IsAlive ( uri , ( long ) pingTime . TotalMilliseconds ) ) {
291+ Debug . WriteLine ( $ "{ uri } isn't alive") ;
292+ return ;
293+ }
279294
280- var di = new DirectImage { Direct = new Uri ( currentUrl ) } ;
295+ if ( ! IsDirect ( currentUrl , directType ) )
296+ return ;
281297
298+ var di = new DirectImage
299+ {
300+ Direct = new Uri ( currentUrl )
301+ } ;
282302
283- bool isValid = ! readImage ;
284303
285- if ( readImage ) {
286- var stream = WebUtilities . GetStream ( currentUrl ) ;
304+ bool isValid = ! readImage ;
287305
288- if ( stream . CanRead ) {
306+ if ( readImage ) {
307+ try {
308+ var img = GetImage ( currentUrl ) ;
289309
290- try {
291- var img = Image . FromStream ( stream ) ;
292- //isValid = true;
310+ isValid = imageFilter ( img ) ;
293311
294- //Debug.WriteLine($"{img.Width} {img.Height}");
295- isValid = imageFilter ( img ) ;
312+ if ( isValid ) {
313+ di . Image = img ;
296314
297- if ( isValid ) {
298- di . Image = img ;
299- }
300- }
301- catch ( Exception ) {
302- isValid = false ;
303- }
315+ }
316+ else {
317+ img . Dispose ( ) ;
304318 }
305319 }
306-
307- if ( directImages . Count >= count ) {
308- return ;
320+ catch ( Exception ) {
321+ isValid = false ;
309322 }
323+ }
310324
311- if ( isValid ) {
312- imagesCopy . Add ( di ) ;
313- //Debug.WriteLine($">>> {currentUrl}");
314-
315- }
325+ if ( imagesCopy . Count >= count ) {
326+ return ;
316327 }
317328
318- //tasks.Add(Task.Factory.StartNew(function, cts.Token));
319- act . Add ( Function ) ;
320- }
329+ if ( isValid ) {
330+ imagesCopy . Add ( di ) ;
331+ }
332+ } ) ;
321333
322334
323335 /*
@@ -343,24 +355,28 @@ void Function()
343355 * 12 3.52
344356 * 13 3.63
345357 * 14 3.52
358+ *
359+ * 15 3.39
360+ * 16 3.52
361+ * 17 3.58
362+ * 18 3.47
363+ * 19 3.33
364+ *
365+ * 20 3.13
366+ * 21 2.89
367+ * 22 2.87
368+ * 23 2.89
346369 */
347370
348- //Task.WaitAll(tasks.ToArray());
349-
350-
351- Parallel . Invoke ( new ParallelOptions ( )
352- {
353- MaxDegreeOfParallelism = Int32 . MaxValue ,
354- TaskScheduler = TaskScheduler . Default ,
355- CancellationToken = cts . Token
356- } , act . ToArray ( ) ) ;
357-
358- sw . Stop ( ) ;
371+ images = imagesCopy ;
359372
360- Trace . WriteLine ( $ " { sw . Elapsed . TotalSeconds } " ) ;
373+ ret :
361374
375+ if ( readImage ) {
376+ images = images . OrderByDescending ( x => x . Image . Width * x . Image . Height ) . ToList ( ) ;
377+ }
362378
363- return directImages . OrderByDescending ( x => x . Image . Width * x . Image . Height ) . ToList ( ) ;
379+ return images ;
364380
365381 }
366382
@@ -375,15 +391,21 @@ internal static string AsPercent(this float n)
375391 }
376392 }
377393
378- public struct DirectImage
394+ public struct DirectImage : IDisposable
379395 {
380396 public Uri Direct { get ; internal set ; }
381397
398+ [ CanBeNull ]
382399 public Image Image { get ; internal set ; }
383400
384401 public override string ToString ( )
385402 {
386- return $ "{ Direct } { Image . Width } x{ Image . Height } ";
403+ return $ "{ Direct } { Image ? . Width } x{ Image ? . Height } ";
404+ }
405+
406+ public void Dispose ( )
407+ {
408+ Image ? . Dispose ( ) ;
387409 }
388410 }
389411
0 commit comments