forked from boostorg/gil
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement hstack and vstack (boostorg#506)
Allow non-equal dims along stack dim Width can be different in hstack, height can be different in vstack
- Loading branch information
1 parent
dab9242
commit ea18604
Showing
2 changed files
with
184 additions
and
80 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
#include "boost/gil/image_view_factory.hpp" | ||
#include <boost/gil/image.hpp> | ||
#include <boost/gil/image_view.hpp> | ||
#include <numeric> | ||
#include <stdexcept> | ||
#include <vector> | ||
|
||
namespace boost { namespace gil { | ||
template <typename View> | ||
void hstack(const std::vector<View>& views, const View& output_view) | ||
{ | ||
if (views.size() == 0) | ||
{ | ||
throw std::invalid_argument("empty views vector is passed - cannot create stacked image"); | ||
} | ||
|
||
auto height = views.front().height(); | ||
auto width = views.front().width(); | ||
for (const auto& view : views) | ||
{ | ||
if (view.height() != height) | ||
{ | ||
throw std::invalid_argument("one or many views are not of the same height"); | ||
} | ||
} | ||
|
||
std::ptrdiff_t full_width = | ||
std::accumulate(views.begin(), views.end(), 0, | ||
[](std::ptrdiff_t old, const View& view) { return old + view.width(); }); | ||
if (output_view.width() != full_width || output_view.height() != height) | ||
{ | ||
throw std::invalid_argument("the destination view is not of the right dimensions"); | ||
} | ||
|
||
std::ptrdiff_t current_x = 0; | ||
for (std::size_t i = 0; i < views.size(); ++i) | ||
{ | ||
auto subview = | ||
subimage_view(output_view, current_x, 0, views[i].width(), views[i].height()); | ||
copy_pixels(views[i], subview); | ||
current_x += views[i].width(); | ||
} | ||
} | ||
|
||
template <typename View> | ||
image<typename View::value_type> hstack(const std::vector<View>& views) | ||
{ | ||
if (views.size() == 0) | ||
{ | ||
throw std::invalid_argument("empty views vector is passed - cannot create stacked image"); | ||
} | ||
|
||
auto dimensions = views.front().dimensions(); | ||
std::ptrdiff_t full_width = | ||
std::accumulate(views.begin(), views.end(), 0, | ||
[](std::ptrdiff_t old, const View& view) { return old + view.width(); }); | ||
std::ptrdiff_t height = views.front().height(); | ||
image<typename View::value_type> result_image(full_width, height); | ||
hstack(views, view(result_image)); | ||
return result_image; | ||
} | ||
|
||
template <typename View> | ||
void vstack(const std::vector<View>& views, const View& output_view) | ||
{ | ||
if (views.size() == 0) | ||
{ | ||
throw std::invalid_argument("empty views vector is passed - cannot create stacked image"); | ||
} | ||
|
||
auto full_height = | ||
std::accumulate(views.begin(), views.end(), 0, | ||
[](std::ptrdiff_t old, const View& view) { return old + view.height(); }); | ||
std::ptrdiff_t width = views.front().height(); | ||
|
||
for (const auto& view : views) | ||
{ | ||
if (view.width() != width) | ||
{ | ||
throw std::invalid_argument("one or many views are not of the same width"); | ||
} | ||
} | ||
|
||
if (output_view != full_height || output_view.width() != width) | ||
{ | ||
throw std::invalid_argument("the destination view is not of the right dimensions"); | ||
} | ||
|
||
std::ptrdiff_t current_y = 0; | ||
for (std::size_t i = 0; i < views.size(); ++i) | ||
{ | ||
auto subview = | ||
subimage_view(output_view, 0, current_y, views[i].width(), views[i].height()); | ||
copy_pixels(views[i], subview); | ||
current_y += views[i].height(); | ||
} | ||
} | ||
|
||
template <typename View> | ||
image<typename View::value_type> vstack(const std::vector<View>& views) | ||
{ | ||
if (views.size() == 0) | ||
{ | ||
throw std::invalid_argument("empty views vector is passed - cannot create stacked image"); | ||
} | ||
|
||
auto full_height = | ||
std::accumulate(views.begin(), views.end(), 0, | ||
[](std::ptrdiff_t old, const View& view) { return old + view.height(); }); | ||
std::ptrdiff_t width = views.front().height(); | ||
|
||
image<typename View::value_type> result_image(width, full_height); | ||
hstack(views, view(result_image)); | ||
return result_image; | ||
} | ||
}} // namespace boost::gil |