diff --git a/include/schaapcommon/math/resampler.h b/include/schaapcommon/math/resampler.h index 03cf7fce8345f3b5d084f56ff4682f9d773d13d8..a558063cd8fad854025751e4895749403dc4b602 100644 --- a/include/schaapcommon/math/resampler.h +++ b/include/schaapcommon/math/resampler.h @@ -16,6 +16,23 @@ namespace schaapcommon::math { +/** + * Class that can resize an image using sinc interpolation. It does this by + * calculating the FT of the image, followed by zero-padding, and + * FT-ing the larger result back to image space. This class has also + * functionality to perform several resampling operation in parallel. + * + * If parallel processing is not necessary, @ref Resample() can be used. + * If only the real-to-complex FT is necessary with the given input dimensions, + * @ref SingleFT() can be used. + * + * Any NaN values are replaced by zeros before FTing. + * + * @TODO The structure of this class is based around older behaviour. It would + * make the functionality easier to by: + * i) make stand-alone functions for SingleFT() and Resample(); + * ii) make use of the thread pool stucture in aocommon for parallelisation. + */ class Resampler { private: struct Task { @@ -23,11 +40,29 @@ class Resampler { }; public: + /** + * Construct a resampler that can increase an image from the input + * dimensions to the output dimensions. + * @TODO The @p cpu_count parameter should be removed, as the resampler + * should use the global thread pool. + */ Resampler(size_t input_width, size_t input_height, size_t output_width, size_t output_height, size_t cpu_count); ~Resampler(); + /** + * Add a task to the queue. Before doing so, @ref Start() must have been + * called. The @p output parameter can be assumed to be finished only + * after @ref Finish() has been called and has returned. If the queue + * is full (all cpus are working), the function will block until + * one of the tasks is finished and a cpu is available. + * + * @param input an array of input_width x input_height values. The + * input will be destroyed. + * @param output array of output_width x output_height values in + * which the resized image will be stored. + */ void AddTask(float* input, float* output) { Task task; task.input = input; @@ -35,12 +70,24 @@ class Resampler { tasks_.write(task); } + /** + * Claim threads and start processing any tasks that are added. This + * function is non-blocking (returns immediately). After calling Start(), + * tasks can be added using @ref AddTask(). Once all tasks are added, + * @ref Finish() should be called. + */ void Start() { for (size_t i = 0; i != tasks_.capacity(); ++i) { threads_.emplace_back(&Resampler::RunThread, this); } } + /** + * Wait until all added tasks have been finished. @ref Start() should + * have been called beforehand. + * After calling @ref Finish(), no more tasks should be added until + * @ref Start() is called. + */ void Finish() { tasks_.write_end(); for (std::thread& t : threads_) t.join(); @@ -48,6 +95,14 @@ class Resampler { tasks_.clear(); } + /** + * Directly perform a single resampling actions. This function does + * not parallelise and blocks until finished. + * @param input an array of input_width x input_height values. The + * input will be destroyed. + * @param output array of output_width x output_height values in + * which the resized image will be stored. + */ void Resample(float* input, float* output) { Task task; task.input = input; @@ -55,11 +110,19 @@ class Resampler { RunSingle(task, false); } + /** + * Directly perform a single real-to-complex Fourier transform. + * @param input Data, with size of input_width x input_height. + * @param real_output Real values after FT-ing, of size input_width x + * input_height. + * @param imaginary_output Corresponding imaginary values. + */ void SingleFT(const float* input, float* real_output, float* imaginary_output); /** - * Only to be used with SingleFT (it makes resampling thread unsafe!) + * Set the resampler to apply a Tukey window during the Fourier transform. + * Only to be used with @ref Resample() (it makes resampling thread unsafe!) */ void SetTukeyWindow(double inset_size, bool correct_window) { window_function_ = aocommon::WindowFunction::Tukey; @@ -70,6 +133,10 @@ class Resampler { window_out_.clear(); } + /** + * Set the resampler to apply a window function during the Fourier transform. + * Only to be used with @ref Resample() (it makes resampling thread unsafe!) + */ void SetWindowFunction(aocommon::WindowFunction::Type window, bool correct_window) { window_function_ = window;