1
\$\begingroup\$

This is a follow-up question for Tests for the operators of image template class in C++, Image pixelwise operation function with multiple inputs in C++ and An Updated Multi-dimensional Image Data Structure with Variadic Template Functions in C++. In order to generate random complex type (std::complex) image, I create a template function named generate_complex_image in this post.

The experimental implementation

  • generate_complex_image template function implementation (in file image_operations.h)

    // generate_complex_image template function implementation
    template<class ElementT>
    requires(std::floating_point<ElementT> || std::integral<ElementT>)
    constexpr static auto generate_complex_image(const Image<ElementT>& real, const Image<ElementT>& imaginary)
    {
     if (real.getSize() != imaginary.getSize())
     {
     throw std::runtime_error("Size mismatched!");
     }
     return pixelwiseOperation(
     [&](auto&& real_element, auto&& imaginary_element)
     {
     return std::complex{ real_element, imaginary_element };
     },
     real,
     imaginary
     );
    }
    
  • pixelwiseOperation template function implementation (in file image_operations.h)

    // pixelwiseOperation template function implementation
    template<std::size_t unwrap_level = 1, class... Args>
    constexpr static auto pixelwiseOperation(auto op, const Args&... inputs)
    {
     auto transformed_data = recursive_transform<unwrap_level>(
     op,
     inputs.getImageData()...);
     auto output = Image<recursive_unwrap_type_t<unwrap_level, decltype(transformed_data)>>(
     transformed_data,
     first_of(inputs...).getSize());
     return output;
    }
    // pixelwiseOperation template function implementation
    template<std::size_t unwrap_level = 1, class ExPo, class InputT>
    requires (std::is_execution_policy_v<std::remove_cvref_t<ExPo>>)
    constexpr static auto pixelwiseOperation(ExPo&& execution_policy, auto op, const Image<InputT>& input1)
    {
     auto transformed_data = recursive_transform<unwrap_level>(
     std::forward<ExPo>(execution_policy),
     op,
     (input1.getImageData()));
     auto output = Image<recursive_unwrap_type_t<unwrap_level, decltype(transformed_data)>>(
     transformed_data,
     input1.getSize());
     return output;
    }
    
  • rand template function implementation (in file image_operations.h)

    // rand template function implementation
    template<image_element_standard_floating_point_type ElementT = double, typename Urbg, class... Sizes>
    requires(std::uniform_random_bit_generator<std::remove_reference_t<Urbg>> and
     ((std::same_as<Sizes, std::size_t>&&...) or
     (std::same_as<Sizes, int>&&...)))
    constexpr static auto rand(Urbg&& urbg, Sizes... sizes)
    {
     // Reference: https://stackoverflow.com/a/23143753/6667035
     // Reference: https://codereview.stackexchange.com/a/294739/231235
     auto dist = std::uniform_real_distribution<ElementT>{};
     return generate([&dist, &urbg]() { return dist(urbg); }, sizes...);
    }
    // rand template function implementation
    template<image_element_standard_floating_point_type ElementT = double, class... Size>
    requires((std::same_as<Size, std::size_t>&&...) or
     (std::same_as<Size, int>&&...))
    inline auto rand(Size... size)
    {
     return rand<ElementT>(std::mt19937{std::random_device{}()}, size...);
    }
    // rand template function implementation
    template<image_element_standard_floating_point_type ElementT = double, typename Urbg>
    requires std::uniform_random_bit_generator<std::remove_reference_t<Urbg>>
    constexpr auto rand(Urbg&& urbg)
    {
     auto dist = std::uniform_real_distribution<ElementT>{};
     return Image<ElementT>(std::vector{ dist(urbg) }, 1, 1);
    }
    // rand template function implementation
    template<image_element_standard_floating_point_type ElementT = double>
    inline auto rand()
    {
     return rand<ElementT>(std::mt19937{std::random_device{}()});
    }
    

The usage of generate_complex_image template function (To generate random complex image):

/* Developed by Jimmy Hu */
#include <chrono>
#include <execution>
#include <map>
#include <omp.h>
#include <sstream>
#include <tbb/global_control.h>
#include "../base_types.h"
#include "../basic_functions.h"
#include "../image.h"
#include "../image_io.h"
#include "../image_operations.h"
#include "../timer.h"
// remove_extension Function Implementation
// Copy from: https://stackoverflow.com/a/6417908/6667035
std::string remove_extension(const std::string& filename)
{
 size_t lastdot = filename.find_last_of(".");
 if (lastdot == std::string::npos) return filename;
 return filename.substr(0, lastdot);
}
void generate_complex_image_tests(const int size = 10)
{
 auto random_complex_image1 =
 TinyDIP::generate_complex_image(
 TinyDIP::rand(size, size),
 TinyDIP::rand(size, size));
 std::cout << "Random complex image size: " << random_complex_image1.getWidth() << "x" << random_complex_image1.getHeight() << '\n';
 std::cout << "Random complex image dimensionality: " << random_complex_image1.getDimensionality() << '\n';
 random_complex_image1.print();
}
int main(int argc, char* argv[])
{
 TinyDIP::Timer timer1;
 generate_complex_image_tests();
 return EXIT_SUCCESS;
}

The output of the test code above:

Random complex image size: 10x10
Random complex image dimensionality: 2
(0.349134,0.058453) (0.204941,0.103249) (0.489626,0.0430718) (0.0287181,0.309311) (0.0399393,0.696768) (0.91164,0.191862) (0.654913,0.866517) (0.297313,0.0406738) (0.363457,0.0659715) (0.0282682,0.226641)
(0.0992994,0.654607) (0.925208,0.580786) (0.40913,0.589028) (0.0422619,0.938065) (0.659919,0.568031) (0.693528,0.305793) (0.324341,0.534812) (0.915293,0.892706) (0.841049,0.443242) (0.926701,0.71971)
(0.161231,0.124854) (0.167118,0.970151) (0.183368,0.808257) (0.0906341,0.37105) (0.435765,0.394986) (0.944431,0.556207) (0.0509784,0.307722) (0.281926,0.368342) (0.373103,0.138894) (0.274492,0.901984)
(0.143554,0.523027) (0.821683,0.303483) (0.994244,0.806173) (0.204999,0.783978) (0.0343751,0.984009) (0.769188,0.0920548) (0.29764,0.896474) (0.15807,0.133722) (0.271,0.631517) (0.206615,0.978604)
(0.771288,0.935558) (0.865369,0.592532) (0.617183,0.649661) (0.224174,0.118173) (0.546682,0.898015) (0.0634438,0.84084) (0.902093,0.633853) (0.774141,0.607455) (0.852407,0.123795) (0.065525,0.662438)
(0.976416,0.557757) (0.0463527,0.999983) (0.715594,0.494586) (0.494334,0.471223) (0.537649,0.822234) (0.2264,0.657272) (0.303286,0.488968) (0.779682,0.114182) (0.535423,0.701713) (0.653509,0.594488)
(0.421601,0.0335276) (0.741846,0.312825) (0.724597,0.0421256) (0.22976,0.271366) (0.101608,0.340671) (0.564151,0.30981) (0.157958,0.731453) (0.513171,0.492235) (0.543436,0.957366) (0.884459,0.575114)
(0.999732,0.683494) (0.526455,0.456438) (0.107317,0.688305) (0.343426,0.880514) (0.965521,0.20274) (0.867809,0.573529) (0.355845,0.103756) (0.292168,0.00579886) (0.969953,0.931475) (0.389777,0.0103169)
(0.325895,0.238896) (0.831035,0.63367) (0.201822,0.954049) (0.654814,0.841531) (0.300335,0.424942) (0.859326,0.247792) (0.840811,0.0560384) (0.961937,0.155272) (0.853906,0.145131) (0.807052,0.398518)
(0.0649945,0.0106254) (0.898195,0.442709) (0.579019,0.310179) (0.853074,0.899483) (0.3355,0.694544) (0.135638,0.326269) (0.945633,0.888922) (0.687101,0.579121) (0.13002,0.951442) (0.278428,0.125251)
Computation finished at Mon Jun 23 15:25:57 2025
 elapsed time: 0.035017 seconds.

TinyDIP on GitHub

All suggestions are welcome.

The summary information:

asked Jun 17 at 8:33
\$\endgroup\$

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.