/// <summary> /// A method that creates anaglyph from the left and right image. /// </summary> /// <param name="dllVersion"> The dll version selected by the user. </param> /// <param name="anaglyphVersion"> User selection of anaglyph version. </param> /// <param name="leftImageInformation"> An instance of the class that stores information about the left image. </param> /// <param name="rightImageInformation"> An instance of the class that stores information about the right image. </param> /// <param name="threadAmount"> Number of threads selected by the user. </param> public void CreateAnaglyph(DllVersion dllVersion, AnaglyphVersion anaglyphVersion, ImageInformation leftImageInformation, ImageInformation rightImageInformation, int threadAmount) { int amountOfPixels = leftImageInformation.imagePixelArray.Length / 4; // the number of pixels that will be modified pixelsForThread = amountOfPixels / threadAmount; // the number of pixels to modify per thread if (pixelsForThread * threadAmount != leftImageInformation.imagePixelArray.Length / 4) // condition checking if the same number of pixels can be processed in each thread (different number of pixels) { int delta = amountOfPixels - (pixelsForThread * threadAmount); // number of pixels remaining PrepareThreads(threadAmount - 1); // prepare tables for the number of threads selected by the user minus one int start = pixelsForThread * (threadAmount - 1); // start index for a thread that modifies the rest of the pixels this.coords.Add(start); // start index for the last thread this.coords.Add(leftImageInformation.imagePixelArray.Length / 4); // end index for the last thread } else // the same number of pixels in each thread { PrepareThreads(threadAmount); // prepare a table of coordinates } anaglyphFilters = new float[12]; // creating an array that stores an anaglyph filter switch (anaglyphVersion) // choosing the right anaglyph filter depending on the user's choice { case AnaglyphVersion.TRUE_ANAGLYPH: anaglyphFilters = AnaglyphOptions._true; break; case AnaglyphVersion.GRAY_ANAGLYPH: anaglyphFilters = AnaglyphOptions._gray; break; case AnaglyphVersion.COLOR_ANAGLYPH: anaglyphFilters = AnaglyphOptions._color; break; case AnaglyphVersion.HALF_COLOR_ANAGLYPH: anaglyphFilters = AnaglyphOptions._halfColor; break; case AnaglyphVersion.OPTIMIZED_ANAGLYPH: anaglyphFilters = AnaglyphOptions._optimized; break; } tmpLeftImagePixelArray = new float[leftImageInformation.imagePixelArray.Length]; // creating a temporary array storing the pixels of the left image for (int i = 0; i < tmpLeftImagePixelArray.Length; i++) // loop that copies the pixel values of the left image into a temporary table { tmpLeftImagePixelArray[i] = leftImageInformation.imagePixelArray[i]; // copy the pixel color value from the left image to a temporary table } switch (dllVersion) // choice of dll depending on the user's choice { case DllVersion.ASM_DLL: // assembler dll choice for (int i = 0; i < this.coords.Count; i += 2) // loop calling as many times as there are coordinates (start and end) for each thread { int[] imageCoords = { this.coords[i] * 4, this.coords[i + 1] * 4 }; // get start and start index for the current thread var th = new Thread(() => // thread creation { AnaglyphAlgorithmAsm(leftImageInformation.imagePixelArray, imageCoords, anaglyphFilters, rightImageInformation.imagePixelArray); }); this.threads.Add(th); // adding a newly created thread to the list of threads } break; case DllVersion.CPP_DLL: // C++ dll choice for (int i = 0; i < this.coords.Count; i += 2) // loop calling as many times as there are coordinates(start and end) for each thread { int[] imageCoords = { this.coords[i] * 4, this.coords[i + 1] * 4 }; // get start and start index for the current thread var th = new Thread(() => // thread creation { AnaglyphAlgorithm(leftImageInformation.imagePixelArray, imageCoords, anaglyphFilters, rightImageInformation.imagePixelArray); }); this.threads.Add(th); // adding a newly created thread to the list of threads } break; } TimerClock.StartTimer(); // counting the time it takes for threads to finish foreach (Thread th in threads) // start all threads { th.Start(); } foreach (Thread th in threads) // waiting for the end of each thread { th.Join(); } TimerClock.StopTimer(); // stop counting time threads.Clear(); // clear the list of threads coords.Clear(); // clearing the list of start and end indexes leftImageInformation.finishConversion(); // creating an image based on returned pixels for (int i = 0; i < tmpLeftImagePixelArray.Length; i++) // copying the pixel color values from the previously created table to the table storing the pixel values of the left image { leftImageInformation.imagePixelArray[i] = tmpLeftImagePixelArray[i]; } EventImageFinished(leftImageInformation.imageBitmap); // reporting an event about the end of anaglyph creation }
/// <summary> /// Called after pressing the button responsible for creating anaglyph. Runs the method from the object instance responsible for creating anaglyph. /// </summary> /// <param name="sender"> object sender </param> /// <param name="e"> RoutedEventArgs </param> private void OnClickButtonGenerateAnaglyph(object sender, RoutedEventArgs e) { if (radioAsm.IsChecked.Value) // assembler dll selected { this.dllVersion = DllVersion.ASM_DLL; } else if (radioC.IsChecked.Value) // C++ dll selected { this.dllVersion = DllVersion.CPP_DLL; } else // no dll selected { this.dllVersion = DllVersion.VOID; } if (radioTrue.IsChecked.Value) // true anaglyph filter selected { this.anaglyphVersion = AnaglyphVersion.TRUE_ANAGLYPH; } else if (radioGray.IsChecked.Value) // gray anaglyph filter selected { this.anaglyphVersion = AnaglyphVersion.GRAY_ANAGLYPH; } else if (radioColor.IsChecked.Value) // color anaglyph filter selected { this.anaglyphVersion = AnaglyphVersion.COLOR_ANAGLYPH; } else if (radioHalfColor.IsChecked.Value) // half color anaglyph filter selected { this.anaglyphVersion = AnaglyphVersion.HALF_COLOR_ANAGLYPH; } else if (radioOptimized.IsChecked.Value) // optimized anaglyph filter selected { this.anaglyphVersion = AnaglyphVersion.OPTIMIZED_ANAGLYPH; } else // no anaglyph filter selected { this.anaglyphVersion = AnaglyphVersion.VOID; } if (this.anaglyphVersion == AnaglyphVersion.VOID || this.dllVersion == DllVersion.VOID) // if anaglyph filter is no selected or dll is no selected display message to user { MessageBox.Show("You must select the DLL and anaglyph type choice!", "Anaglyph Creator Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } // checking if the images are the same size if (this.leftImage.GetImageInformation().imageSizeX != this.rightImage.GetImageInformation().imageSizeX || this.leftImage.GetImageInformation().imageSizeY != this.rightImage.GetImageInformation().imageSizeY) { MessageBox.Show("Left and right images must be the same size!", "Wrong image sizes", MessageBoxButton.OK, MessageBoxImage.Error); return; } // checking if there are dll files if (this.dllVersion == DllVersion.CPP_DLL && !File.Exists("DLL_C.dll")) { MessageBox.Show("No DLL found for the C++ algorithm!", "C++ DLL missing", MessageBoxButton.OK, MessageBoxImage.Error); return; } else if (this.dllVersion == DllVersion.ASM_DLL && !File.Exists("DLL_ASM.dll")) { MessageBox.Show("No DLL found for the assembler algorithm!", "Asm DLL missing", MessageBoxButton.OK, MessageBoxImage.Error); return; } TimerClock.ResetTimer(); // reset timer that measures algorithm time int threadsAmount = (int)this.threadsBar.Value; // getting the number of threads this.buttonGenerateAnaglyph.IsEnabled = false; // turning off the generate button while creating anaglyph new Thread(() => { Thread.CurrentThread.IsBackground = true; anaglyph.CreateAnaglyph(this.dllVersion, this.anaglyphVersion, rightImage.GetImageInformation(), leftImage.GetImageInformation(), threadsAmount); }).Start(); // invoke method that creates anaglyph }