private void SetWindowFieldsData(ResultDetails details) { // Basic info this.txtbTimeEllapsed.Text = details.EllapsedTime.ToString(); this.txtbSearchesPerformed.Text = details.ImageSearchTimes.ToString(); this.txtbRanAsync.Text = details.IsSynchronousOperationPerformed ? "No" : "Yes"; this.txtbImageScaledDownTimes.Text = details.ImageResizedTimes.ToString(); Rectangle smallImageRect = details.IsSynchronousOperationPerformed ? details.SyncImageSearchResults.First() : details.AsyncImageSearchResults.Select(x => x.Value).First(); var originalSmallImageRect = new Rectangle(); // Resized image info if (details.ImageResizedTimes > 0) { int scaleRatio = (details.ImageResizedTimes + 1); this.grdResizedImages.Visibility = Visibility.Visible; this.txtbResizedLargeImageSize.Text = $"W: {(int)(details.OriginalLargeImageWidth / scaleRatio)}, H: {(int)(details.OriginalLargeImageHeight / scaleRatio)}"; this.txtbResizedSmallImageSize.Text = $"W: {smallImageRect.Width}, H: {smallImageRect.Height}"; this.txtbResizedSmallImagePos.Text = $"X: {smallImageRect.X}, Y: {smallImageRect.Y}"; originalSmallImageRect = _imageLogic.CalculateImageOriginalSizeAndPosition(smallImageRect, details.ImageResizedTimes); } // Original image info this.txtbOriginalLargeImageSize.Text = $"W: {details.OriginalLargeImageWidth}, H: {details.OriginalLargeImageHeight}"; this.txtbOriginalSmallImageSize.Text = $"W: {originalSmallImageRect.Width}, H: {originalSmallImageRect.Height}"; this.txtbOriginalSmallImagePos.Text = $"X: {originalSmallImageRect.X}, Y: {originalSmallImageRect.Y}"; }
private async void btnSearchMatchingImages_Click(object sender, RoutedEventArgs e) { // No need to perform any other operations if image file paths are not given if (string.IsNullOrEmpty(this.txtLargeImagePath.Text) || string.IsNullOrEmpty(this.txtSmallImagePath.Text)) { System.Windows.Forms.MessageBox.Show("All fields must be filled!"); return; } int scaleDownTimes = (int)this.slValue.Value; string resizedLargeImagePath = this.txtLargeImagePath.Text.Replace(Path.GetFileNameWithoutExtension(this.txtLargeImagePath.Text), ResizedLargeImageNameWithoutExtension); string resizedSmallImagePath = this.txtSmallImagePath.Text.Replace(Path.GetFileNameWithoutExtension(this.txtSmallImagePath.Text), ResizedSmallImageNameWithoutExtension); // Clear previous data and files _syncImageSearchResults.Clear(); _asyncImageSearchResults.Clear(); _resultDetails = null; File.Delete(resizedLargeImagePath); File.Delete(resizedSmallImagePath); _imageLogic.DeletePreviousRectangleImages(Path.GetDirectoryName(this.txtLargeImagePath.Text)); if (scaleDownTimes > 0) { _imageLogic.ResizeImageAndSave(this.txtLargeImagePath.Text, resizedLargeImagePath, scaleDownTimes, 90L); _imageLogic.ResizeImageAndSave(this.txtSmallImagePath.Text, resizedSmallImagePath, scaleDownTimes, 90L); } // Gets corresponding file path depending whether images has been resized or not string largeImgPath = scaleDownTimes > 0 ? resizedLargeImagePath : this.txtLargeImagePath.Text; string smallImgPath = scaleDownTimes > 0 ? resizedSmallImagePath : this.txtSmallImagePath.Text; var watch = System.Diagnostics.Stopwatch.StartNew(); _tokenSource = new CancellationTokenSource(); var pOptions = new ParallelOptions(); var ui = TaskScheduler.FromCurrentSynchronizationContext(); pOptions.CancellationToken = _tokenSource.Token; int imageSearchTimes = (int)this.slImageSearchTimes.Value; bool isSynchronousOperation = this.rbtnRunSync.IsChecked == true; // Update the UI before search has been started this.txtStatus.Text = "In progress"; this.btnCancelSearch.IsEnabled = true; this.btnSearchMatchingImages.IsEnabled = false; this.btnViewDetails.IsEnabled = false; try { await Task.Factory.StartNew(() => { if (isSynchronousOperation) { for (int i = 0; i < imageSearchTimes; i++) { Rectangle rect = _computingLogic.GetImageParamsResult(largeImgPath, smallImgPath); _syncImageSearchResults.Add(rect); } } else { Parallel.For(0, imageSearchTimes, i => { Rectangle rect = _computingLogic.GetImageParamsResult(largeImgPath, smallImgPath); _asyncImageSearchResults.TryAdd(i, rect); // The way to exit the parallel for-each loop pOptions.CancellationToken.ThrowIfCancellationRequested(); }); } }, _tokenSource.Token) .ContinueWith((t) => { _tokenSource.Dispose(); _tokenSource = null; watch.Stop(); long elapsedMs = watch.ElapsedMilliseconds; // Save result images where red rectangle is drawn string rectLargeImagePath = this.txtLargeImagePath.Text.Replace(Path.GetFileNameWithoutExtension(this.txtLargeImagePath.Text), "rect_" + Path.GetFileNameWithoutExtension(this.txtLargeImagePath.Text)); string resizedRectLargeImagePath = string.Empty; if (scaleDownTimes > 0) { resizedRectLargeImagePath = resizedLargeImagePath.Replace(Path.GetFileNameWithoutExtension(resizedLargeImagePath), "rect_" + ResizedLargeImageNameWithoutExtension); Rectangle resizedSmallImageRect = this.GetSingleImageSearchResult(isSynchronousOperation); // We want to get the original function position and size on the screen. // Functions are scaled down only to increase performance! Rectangle originalImageRect = _imageLogic.CalculateImageOriginalSizeAndPosition(resizedSmallImageRect, scaleDownTimes); _imageLogic.DrawRectangleOntoImageAndSave(this.txtLargeImagePath.Text, rectLargeImagePath, originalImageRect); _imageLogic.DrawRectangleOntoImageAndSave(resizedLargeImagePath, resizedRectLargeImagePath, this.GetSingleImageSearchResult(isSynchronousOperation)); } else { _imageLogic.DrawRectangleOntoImageAndSave(this.txtLargeImagePath.Text, rectLargeImagePath, this.GetSingleImageSearchResult(isSynchronousOperation)); } var originalLargeImage = Image.FromFile(this.txtLargeImagePath.Text); // Map result details information _resultDetails = new ResultDetails() { OriginalLargeImageWidth = originalLargeImage.Width, OriginalLargeImageHeight = originalLargeImage.Height, EllapsedTime = elapsedMs, ImageResizedTimes = scaleDownTimes, AsyncImageSearchResults = _asyncImageSearchResults, SyncImageSearchResults = _syncImageSearchResults, ImageSearchTimes = imageSearchTimes, RectLargeImagePath = rectLargeImagePath, ResizedRectLargeImagePath = resizedRectLargeImagePath, IsSynchronousOperationPerformed = isSynchronousOperation, }; originalLargeImage.Dispose(); // Update UI after search has been completed this.lblElapsedTime.Content = "Ellapsed time(ms): " + elapsedMs; this.txtStatus.Text = "Ready"; this.btnCancelSearch.IsEnabled = false; this.btnSearchMatchingImages.IsEnabled = true; this.btnViewDetails.IsEnabled = true; }, _tokenSource.Token, TaskContinuationOptions.OnlyOnRanToCompletion, ui); } catch (OperationCanceledException) { } catch (ObjectDisposedException) { } catch (AggregateException ex) { ex.Handle((x) => { return(true); }); System.Windows.Forms.MessageBox.Show(ex.Message); } catch (Exception) { } }