diff --git a/example/rasterizer_circle.cpp b/example/rasterizer_circle.cpp index 2c56de3199..0ab36ddf0f 100644 --- a/example/rasterizer_circle.cpp +++ b/example/rasterizer_circle.cpp @@ -8,6 +8,7 @@ #include #include + #include #include #include @@ -15,8 +16,8 @@ namespace gil = boost::gil; // Demonstrates the use of a rasterizer to generate an image of a circle -// The various rasterizers available are defined in include/boost/gil/rasterization/circle.hpp, -// include/boost/gil/rasterization/ellipse.hpp and include/boost/gil/rasterization/line.hpp +// The various rasterizers available are defined in include/boost/gil/extension/rasterization/circle.hpp, +// include/boost/gil/extension/rasterization/ellipse.hpp and include/boost/gil/extension/rasterization/line.hpp // This example uses a trigonometric rasterizer; GIL also offers the rasterizer midpoint_circle_rasterizer, // which implements the Midpoint algorithm. // See also: diff --git a/example/rasterizer_ellipse.cpp b/example/rasterizer_ellipse.cpp index 295fe0533c..d34ba53635 100644 --- a/example/rasterizer_ellipse.cpp +++ b/example/rasterizer_ellipse.cpp @@ -6,14 +6,14 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include #include +#include namespace gil = boost::gil; // Demonstrates the use of a rasterizer to generate an image of an ellipse -// The various rasterizers available are defined in include/boost/gil/rasterization/circle.hpp, -// include/boost/gil/rasterization/ellipse.hpp and include/boost/gil/rasterization/line.hpp +// The various rasterizers available are defined in include/boost/gil/extension/rasterization/circle.hpp, +// include/boost/gil/extension/rasterization/ellipse.hpp and include/boost/gil/extension/rasterization/line.hpp // The rasterizer used is a generalisation of the midpoint algorithm often used for drawing circle. // This examples also shows how to create images with various pixel depth, as well as the behaviour // in case of the rasterization of a curve that doesn't fit in a view. @@ -25,28 +25,28 @@ namespace gil = boost::gil; int main() { // Syntax for usage :- - // auto rasterizer = gil::midpoint_elliptical_rasterizer{}; - // rasterizer(img_view, colour, center, semi-axes_length); + // auto rasterizer = gil::midpoint_ellipse_rasterizer{}; + // rasterizer(img_view, pixel, center, semi-axes_length); // Where // img_view : gil view of the image on which ellipse is to be drawn. - // colour : Vector containing channel intensity values for img_view. Number of colours - // provided must be equal to the number of channels present in img_view. - // center : Array containing positive integer x co-ordinate and y co-ordinate of the center + // pixel : Pixel value for the elliptical curve to be drawn. Pixel's type must be compatible to the + // pixel type of the image view. + // center : Point containing positive integer x co-ordinate and y co-ordinate of the center // respectively. - // semi-axes_length : Array containing positive integer lengths of horizontal semi-axis + // semi-axes_length : Point containing positive integer lengths of horizontal semi-axis // and vertical semi-axis respectively. gil::gray8_image_t gray_buffer_image(256, 256); - auto gray_elliptical_rasterizer = gil::midpoint_elliptical_rasterizer{}; - gray_elliptical_rasterizer(view(gray_buffer_image), {128}, {128, 128}, {100, 50}); + auto gray_ellipse_rasterizer = gil::midpoint_ellipse_rasterizer{}; + gray_ellipse_rasterizer(view(gray_buffer_image), gil::gray8_pixel_t{128}, {128, 128}, {100, 50}); gil::rgb8_image_t rgb_buffer_image(256, 256); - auto rgb_elliptical_rasterizer = gil::midpoint_elliptical_rasterizer{}; - rgb_elliptical_rasterizer(view(rgb_buffer_image), {0, 0, 255}, {128, 128}, {50, 100}); + auto rgb_ellipse_rasterizer = gil::midpoint_ellipse_rasterizer{}; + rgb_ellipse_rasterizer(view(rgb_buffer_image), gil::rgb8_pixel_t{0, 0, 255}, {128, 128}, {50, 100}); gil::rgb8_image_t rgb_buffer_image_out_of_bound(256, 256); - auto rgb_elliptical_rasterizer_out_of_bound = gil::midpoint_elliptical_rasterizer{}; - rgb_elliptical_rasterizer_out_of_bound(view(rgb_buffer_image_out_of_bound), {255, 0, 0}, + auto rgb_ellipse_rasterizer_out_of_bound = gil::midpoint_ellipse_rasterizer{}; + rgb_ellipse_rasterizer_out_of_bound(view(rgb_buffer_image_out_of_bound), gil::rgb8_pixel_t{255, 0, 0}, {100, 100}, {160, 160}); gil::write_view("rasterized_ellipse_gray.jpg", view(gray_buffer_image), gil::jpeg_tag{}); diff --git a/example/rasterizer_line.cpp b/example/rasterizer_line.cpp index 7b2aec35b1..026ad10d9a 100644 --- a/example/rasterizer_line.cpp +++ b/example/rasterizer_line.cpp @@ -15,8 +15,8 @@ namespace gil = boost::gil; // Demonstrates the use of a rasterizer to generate an image of a line -// The various rasterizers available are defined in include/boost/gil/rasterization/circle.hpp, -// include/boost/gil/rasterization/ellipse.hpp and include/boost/gil/rasterization/line.hpp +// The various rasterizers available are defined in include/boost/gil/extension/rasterization/circle.hpp, +// include/boost/gil/extension/rasterization/ellipse.hpp and include/boost/gil/extension/rasterization/line.hpp // The rasterizer used implements the Bresenham's line algorithm. // Multiple images are created, all of the same size, but with areas of different sizes passed to the rasterizer, resulting in different lines. // See also: diff --git a/include/boost/gil/extension/rasterization/ellipse.hpp b/include/boost/gil/extension/rasterization/ellipse.hpp index 6ea6ea46cb..2f9aca9442 100644 --- a/include/boost/gil/extension/rasterization/ellipse.hpp +++ b/include/boost/gil/extension/rasterization/ellipse.hpp @@ -8,9 +8,12 @@ #ifndef BOOST_GIL_EXTENSION_RASTERIZATION_ELLIPSE_HPP #define BOOST_GIL_EXTENSION_RASTERIZATION_ELLIPSE_HPP +#include +#include + #include +#include #include -#include namespace boost { namespace gil { @@ -22,21 +25,21 @@ namespace boost { namespace gil { /// \brief Performs ellipse rasterization using midpoint algorithm. Initially, program considers /// origin as center of ellipse and obtains first quadrant trajectory points. After that, /// it shifts origin to provided co-ordinates of center and then draws the curve. -struct midpoint_elliptical_rasterizer +struct midpoint_ellipse_rasterizer { /// \brief Returns a vector containing co-ordinates of first quadrant points which lie on /// rasterizer trajectory of the ellipse. - /// \param semi_axes - Array containing half of lengths of horizontal and vertical axis + /// \param semi_axes - Point containing half of lengths of horizontal and vertical axis /// respectively. - auto obtain_trajectory(std::array const semi_axes) - -> std::vector> + auto obtain_trajectory(point semi_axes) + -> std::vector { // Citation : J. Van Aken, "An Efficient Ellipse-Drawing Algorithm" in IEEE Computer // Graphics and Applications, vol. 4, no. 09, pp. 24-35, 1984. // doi: 10.1109/MCG.1984.275994 // keywords: {null} // url: https://doi.ieeecomputersociety.org/10.1109/MCG.1984.275994 - std::vector> trajectory_points; + std::vector trajectory_points; std::ptrdiff_t x = semi_axes[0], y = 0; // Variables declared on following lines are temporary variables used for improving @@ -96,58 +99,63 @@ struct midpoint_elliptical_rasterizer /// obtained from their reflection along major axis, minor axis and line passing through /// center with slope -1 using colours provided by user. /// \param view - Gil view of image on which the elliptical curve is to be drawn. - /// \param colour - Constant vector specifying colour intensity values for all channels present - /// in 'view'. - /// \param center - Constant array specifying co-ordinates of center of ellipse to be drawn. + /// \param pixel - Pixel value for the elliptical curve to be drawn. + /// \param center - Point specifying co-ordinates of center of ellipse to be drawn. /// \param trajectory_points - Constant vector specifying pixel co-ordinates of points lying /// on rasterizer trajectory. /// \tparam View - Type of input image view. - template - void draw_curve(View view, std::vector const colour, - std::array const center, - std::vector> const trajectory_points) + /// \tparam Pixel - Type of pixel. Must be compatible to the pixel type of the image view + template + void draw_curve(View& view, Pixel const& pixel, + point center, + std::vector const& trajectory_points) { - for (int i = 0, colour_index = 0; i < static_cast(view.num_channels()); - ++i, ++colour_index) + using pixel_t = typename View::value_type; + if (!pixels_are_compatible()) { - for (std::array point : trajectory_points) + throw std::runtime_error("Pixel type of the given image is not compatible to the " + "type of the provided pixel."); + } + + --center[0], --center[1]; // For converting center co-ordinate values to zero based indexing. + for (point_t pnt : trajectory_points) + { + std::array co_ords = {center[0] + pnt[0], + center[0] - pnt[0], center[1] + pnt[1], center[1] - pnt[1] + }; + bool validity[4]{}; + if (co_ords[0] < view.width()) + { + validity[0] = true; + } + if (co_ords[1] >= 0 && co_ords[1] < view.width()) { - std::array co_ords = {center[0] + point[0], - center[0] - point[0], center[1] + point[1], center[1] - point[1] - }; - bool validity[4] = {0}; - if (co_ords[0] < view.width()) - { - validity[0] = 1; - } - if (co_ords[1] >= 0 && co_ords[1] < view.width()) - { - validity[1] = 1; - } - if (co_ords[2] < view.height()) - { - validity[2] = 1; - } - if (co_ords[3] >= 0 && co_ords[3] < view.height()) - { - validity[3] = 1; - } - if (validity[0] && validity[2]) - { - nth_channel_view(view, i)(co_ords[0], co_ords[2])[0] = colour[colour_index]; - } - if (validity[1] && validity[2]) - { - nth_channel_view(view, i)(co_ords[1], co_ords[2])[0] = colour[colour_index]; - } - if (validity[1] && validity[3]) - { - nth_channel_view(view, i)(co_ords[1], co_ords[3])[0] = colour[colour_index]; - } - if (validity[0] && validity[3]) - { - nth_channel_view(view, i)(co_ords[0], co_ords[3])[0] = colour[colour_index]; - } + validity[1] = true; + } + if (co_ords[2] < view.height()) + { + validity[2] = true; + } + if (co_ords[3] >= 0 && co_ords[3] < view.height()) + { + validity[3] = true; + } + + if (validity[0] && validity[2]) + { + view(co_ords[0], co_ords[2]) = pixel; + } + if (validity[1] && validity[2]) + { + view(co_ords[1], co_ords[2]) = pixel; + } + if (validity[1] && validity[3]) + { + view(co_ords[1], co_ords[3]) = pixel; + } + if (validity[0] && validity[3]) + { + view(co_ords[0], co_ords[3]) = pixel; } } } @@ -155,37 +163,18 @@ struct midpoint_elliptical_rasterizer /// \brief Calls the function 'obtain_trajectory' and then passes obtained trajectory points /// in the function 'draw_curve' for drawing the desired ellipse. /// \param view - Gil view of image on which the elliptical curve is to be drawn. - /// \param colour - Constant vector specifying colour intensity values for all channels present - /// in 'view'. - /// \param center - Array containing positive integer x co-ordinate and y co-ordinate of the + /// \param pixel - Pixel value for the elliptical curve to be drawn. + /// \param center - Point containing positive integer x co-ordinate and y co-ordinate of the /// center respectively. - /// \param semi_axes - Array containing positive integer lengths of horizontal semi-axis + /// \param semi_axes - Point containing positive integer lengths of horizontal semi-axis /// and vertical semi-axis respectively. /// \tparam View - Type of input image view. - template - void operator()(View view, std::vector const colour, - std::array center, std::array const semi_axes) + /// \tparam Pixel - Type of pixel. Must be compatible to the pixel type of the image view + template + void operator()(View& view, Pixel const& pixel, + point center, point semi_axes) { - --center[0], --center[1]; // For converting center co-ordinate values to zero based indexing. - if (colour.size() != view.num_channels()) - { - throw std::length_error("Number of channels in given image is not equal to the " - "number of colours provided."); - } - if (center[0] + semi_axes[0] >= view.width() || center[1] + semi_axes[1] >= view.height() - || static_cast(center[0] - semi_axes[0]) < 0 - || static_cast(center[0] - semi_axes[0]) >= view.width() - || static_cast(center[1] - semi_axes[1]) < 0 - || static_cast(center[1] - semi_axes[1]) >= view.height()) - { - std::cout << "Image can't contain whole curve.\n" - "However, it will contain those parts of curve which can fit inside it.\n" - "Note : Image width = " << view.width() << " and Image height = " << - view.height() << "\n"; - } - std::vector> trajectory_points = - obtain_trajectory(semi_axes); - draw_curve(view, colour, center, trajectory_points); + draw_curve(view, pixel, center, obtain_trajectory(semi_axes)); } }; diff --git a/test/extension/rasterization/ellipse.cpp b/test/extension/rasterization/ellipse.cpp index 495e40400a..1b44707917 100644 --- a/test/extension/rasterization/ellipse.cpp +++ b/test/extension/rasterization/ellipse.cpp @@ -6,8 +6,8 @@ // http://www.boost.org/LICENSE_1_0.txt) // #include -#include "boost/gil.hpp" -#include +#include + #include #include @@ -17,7 +17,7 @@ namespace gil = boost::gil; // is equal to the length of major axis of the ellipse. // Parameters b and a represent half of lengths of vertical and horizontal axis respectively. void test_rasterizer_follows_equation( - std::vector> trajectory_points, float a, float b) + std::vector const& trajectory_points, float a, float b) { float focus_x, focus_y; if (a > b) // For horizontal ellipse @@ -34,7 +34,7 @@ void test_rasterizer_follows_equation( for (auto trajectory_point : trajectory_points) { // To suppress conversion warnings from compiler - std::array point { + gil::point point { static_cast(trajectory_point[0]), static_cast(trajectory_point[1])}; double dist_sum = std::sqrt(std::pow(focus_x - point[0], 2) + @@ -53,7 +53,7 @@ void test_rasterizer_follows_equation( // This function verifies that the difference between x co-ordinates and y co-ordinates for two // successive trajectory points is less than or equal to 1. This ensures that the curve is connected. -void test_connectivity(std::vector> points) +void test_connectivity(std::vector const& points) { for (std::size_t i = 1; i < points.size(); ++i) { @@ -72,8 +72,8 @@ int main() { for (float b = 1; b < 101; ++b) { - auto rasterizer = gil::midpoint_elliptical_rasterizer{}; - std::vector> points = rasterizer.obtain_trajectory( + auto rasterizer = gil::midpoint_ellipse_rasterizer{}; + std::vector points = rasterizer.obtain_trajectory( {static_cast(a), static_cast(b)}); test_rasterizer_follows_equation(points, a, b); test_connectivity(points);