// Copyright (C) 2008 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_DRAW_IMAGe_ #define DLIB_DRAW_IMAGe_ #include "draw_abstract.h" #include "../algs.h" #include "../pixel.h" #include "../matrix.h" #include <cmath> namespace dlib { // ---------------------------------------------------------------------------------------- template < typename image_type, typename pixel_type > void draw_line ( long x1, long y1, long x2, long y2, image_type& c, const pixel_type& val ) { if (x1 == x2) { // make sure y1 comes before y2 if (y1 > y2) swap(y1,y2); if (x1 < 0 || x1 >= c.nc()) return; // this is a vertical line for (long y = y1; y <= y2; ++y) { if (y < 0 || y >= c.nr()) continue; assign_pixel(c[y][x1], val); } } else if (y1 == y2) { // make sure x1 comes before x2 if (x1 > x2) swap(x1,x2); if (y1 < 0 || y1 >= c.nr()) return; // this is a horizontal line for (long x = x1; x <= x2; ++x) { if (x < 0 || x >= c.nc()) continue; assign_pixel(c[y1][x] , val); } } else { const long rise = (((long)y2) - ((long)y1)); const long run = (((long)x2) - ((long)x1)); if (std::abs(rise) < std::abs(run)) { const double slope = ((double)rise)/run; double first, last; if (x1 > x2) { first = x2; last = x1; } else { first = x1; last = x2; } long y; long x; const double x1f = x1; const double y1f = y1; for (double i = first; i <= last; ++i) { y = static_cast<long>(slope*(i-x1f) + y1f); x = static_cast<long>(i); if (y < 0 || y >= c.nr()) continue; if (x < 0 || x >= c.nc()) continue; assign_pixel(c[y][x] , val); } } else { const double slope = ((double)run)/rise; double first, last; if (y1 > y2) { first = y2; last = y1; } else { first = y1; last = y2; } long x; long y; const double x1f = x1; const double y1f = y1; for (double i = first; i <= last; ++i) { x = static_cast<long>(slope*(i-y1f) + x1f); y = static_cast<long>(i); if (x < 0 || x >= c.nc()) continue; if (y < 0 || y >= c.nr()) continue; assign_pixel(c[y][x] , val); } } } } // ---------------------------------------------------------------------------------------- template < typename image_type, typename pixel_type > void draw_line ( image_type& c, const point& p1, const point& p2, const pixel_type& val ) { draw_line(p1.x(),p1.y(),p2.x(),p2.y(),c,val); } // ---------------------------------------------------------------------------------------- template < typename image_type, typename pixel_type > void draw_rectangle ( image_type& c, const rectangle& rect, const pixel_type& val ) { draw_line(c, rect.tl_corner(), rect.tr_corner(), val); draw_line(c, rect.bl_corner(), rect.br_corner(), val); draw_line(c, rect.tl_corner(), rect.bl_corner(), val); draw_line(c, rect.tr_corner(), rect.br_corner(), val); } // ---------------------------------------------------------------------------------------- template < typename image_type, typename pixel_type > void draw_rectangle ( image_type& c, const rectangle& rect, const pixel_type& val, unsigned int thickness ) { for (int i = 0; i < thickness; ++i) { if ((i%2)==0) draw_rectangle(c,shrink_rect(rect,(i+1)/2),val); else draw_rectangle(c,grow_rect(rect,(i+1)/2),val); } } // ---------------------------------------------------------------------------------------- template < typename image_type, typename pixel_type > void fill_rect ( image_type& img, const rectangle& rect, const pixel_type& pixel ) { rectangle area = rect.intersect(get_rect(img)); for (long r = area.top(); r <= area.bottom(); ++r) { for (long c = area.left(); c <= area.right(); ++c) { assign_pixel(img[r][c], pixel); } } } // ---------------------------------------------------------------------------------------- template < typename image_array_type > matrix<typename image_array_type::value_type::type> tile_images ( const image_array_type& images ) { typedef typename image_array_type::value_type::type T; if (images.size() == 0) return matrix<T>(); const unsigned long size_nc = square_root(images.size()); const unsigned long size_nr = (size_nc*(size_nc-1)>=images.size())? size_nc-1 : size_nc; // Figure out the size we have to use for each chip in the big main image. We will // use the largest dimensions seen across all the chips. long nr = 0; long nc = 0; for (unsigned long i = 0; i < images.size(); ++i) { nr = std::max(images[i].nr(), nr); nc = std::max(images[i].nc(), nc); } matrix<T> temp(size_nr*nr, size_nc*nc); T background_color; assign_pixel(background_color, 0); temp = background_color; unsigned long idx = 0; for (long r = 0; r < size_nr; ++r) { for (long c = 0; c < size_nc; ++c) { if (idx < images.size()) { set_subm(temp, r*nr, c*nc, nr, nc) = mat(images[idx]); } ++idx; } } return temp; } // ---------------------------------------------------------------------------------------- } #endif // DLIB_DRAW_IMAGe_