KJB
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
i_image.h
Go to the documentation of this file.
1 
7 /*
8  * $Id: i_image.h 18301 2014-11-26 19:17:13Z ksimek $
9  */
10 
11 #ifndef KJB_CPP_IMAGE_H
12 #define KJB_CPP_IMAGE_H
13 
14 //#include "m_cpp/m_concept.h"
15 #include "i/i_matrix.h"
16 #include "i/i_float.h"
17 #include "i/i_float_io.h"
18 #include "i/i_transform.h"
19 #include "i/i_arithmetic.h"
20 #include "i/i_draw.h"
21 #include "i2/i2_draw_text.h"
22 
23 // if not for intensity_histogram(), we could remove all
24 // dependencies to m_cpp from i_image.h . Consider moving to
25 // i2_cpp.
26 #include "m_cpp/m_vector.h"
27 #include "m_cpp/m_matrix.h"
28 
29 #include <boost/shared_ptr.hpp>
30 //#include <boost/concept_check.hpp>
31 
32 //define YES_WE_WANT_GARBAGE_POLICE /* for debugging */
33 
34 #include <string>
35 #include <exception>
36 #include <stdexcept>
37 #ifdef YES_WE_WANT_GARBAGE_POLICE
38 #include <sstream>
39 #endif
40 
41 namespace kjb
42 {
43  class Matrix;
44  class Int_matrix;
45  class Vector;
46 
57 // some trivial forward declaration stuff we need
58 class Image;
59 Image scale_image(const Image&, double);
60 Image get_inverted(const Image&);
61 Image rgb_matrices_to_image(const Matrix&, const Matrix&, const Matrix&);
62 
63 
64 
76 class Image
77 {
78 public:
79  typedef kjb_c::KJB_image Impl_type;
80  typedef kjb_c::Pixel Pixel_type;
81 
82 protected:
84 
85 private:
86  static const char* BAD_CHANNEL;
87 
88  static
89  void sort2( int& smaller, int& bigger )
90  {
91  if ( smaller > bigger )
92  {
93  std::swap( smaller, bigger );
94  }
95  }
96 
97  void compute_row_col( int index, int* row, int* col ) const
98  {
99  // Test program was HERE.
100  *row = index / get_num_cols();
101  *col = index - *row * get_num_cols();
102  }
103 
104  void compute_row_col_carefully( int index, int* row, int* col ) const
105  {
106  if ( 0 == get_num_cols() )
107  {
108  *row = *col = 0;
109  }
110  else
111  {
112  // Test program was HERE.
113  compute_row_col( index, row, col );
114  }
115  }
116 
117 #ifdef YES_WE_WANT_GARBAGE_POLICE
118  mutable std::string info;
119  static int live_object_counter;
120  static int serial_counter;
121 #endif
122 
123  void call_me_in_every_ctor()
124  {
125 #ifdef YES_WE_WANT_GARBAGE_POLICE
126  ++live_object_counter;
127  ++serial_counter;
128  std::ostringstream s;
129  s << '(' << serial_counter << ')';
130  info = s.str() + info;
131 #endif
132  }
133 
134 
135 
136 public:
137 
138 
141 
143  Image(int rows = 0, int cols = 0);
144 
146  explicit Image( const kjb_c::Matrix& src );
147 
149  explicit Image( const Matrix& src );
150 
152  Image( const Image& src );
153 
154 #ifdef KJB_HAVE_CXX11
155 
158  Image(Image&& src)
159  : m_image( nullptr )
160  {
161  m_image = src.m_image;
162  src.m_image = 0;
163  }
164 #endif /* KJB_HAVE_CXX11 */
165 
166 
167 
174  explicit Image(const std::string& fname);
175 
177  explicit Image( Impl_type* wrap_me );
178 
182  Image(int num_rows, int num_cols, int r, int g, int b);
183 
184  /* /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ */
185 
186  /*---------------------------------------------------------------------*
187  * "NAMED CONSTRUCTORS"
188  *---------------------------------------------------------------------*/
189 
193  static
194  Image create_zero_image( int rows, int cols )
195  {
196  return create_initialized_image( rows, cols, 0, 0, 0 );
197  }
198 
202  static
203  Image create_initialized_image( int rows, int cols, int r, int g, int b );
204 
205  /* /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ */
206 
207 
209  virtual ~Image()
210  {
211  #ifdef YES_WE_WANT_GARBAGE_POLICE
212  fprintf( stderr, "DTOR: %s\n", info.c_str() );
213  --live_object_counter;
214  #endif
215 
216  kjb_c::kjb_free_image(m_image);
217  }
218 
220  void swap( Image& other )
221  {
222  using std::swap;
223  swap( m_image, other.m_image );
224  }
225 
226  friend void swap(kjb::Image& a, kjb::Image& b)
227  {
228  a.swap(b);
229  }
230 
233  Image& scale(double factor)
234  {
235  Image i(scale_image(*this, factor));
236  swap(i);
237  return *this;
238  }
239 
241  Image& crop(int r, int c, int num_rows, int num_cols);
242 
243  #ifdef YES_WE_WANT_GARBAGE_POLICE
244  void infocat( const std::string& concat_me ) const { info += concat_me; }
246  std::string get_info() const { return info; }
247  static int query_live_counter() { return live_object_counter; }
248  static int query_serial_counter() { return serial_counter; }
249  #endif
250 
251 
253  void write(const std::string& fname) const;
254 
256  int get_num_rows() const
257  {
258  return m_image->num_rows;
259  }
260 
262  int get_num_cols() const
263  {
264  return m_image->num_cols;
265  }
266 
268  int get_length() const
269  {
270  return get_num_rows() * get_num_cols();
271  }
272 
274  Image& operator=(const kjb_c::KJB_image& src);
275 
277  Image& operator=(const Image& src);
278 
279 #ifdef KJB_HAVE_CXX11
280 
283  Image& operator=(Image&& other)
284  {
285  if(this == &other)
286  return *this;
287 
288  kjb_c::kjb_free_image( m_image );
289  m_image = other.m_image;
290  other.m_image = 0;
291  return *this;
292  }
293 #endif /* KJB_HAVE_CXX11 */
294 
296  Image& operator+=(const Image& op2);
297 
299  Image& operator-=(const Image& op2);
300 
306  Image& operator*=(double op2);
307 
314  Image& operator/=(double op2);
315 
321  float& operator()(int row, int col, int channel)
322  {
323  // Test program was HERE.
324  switch(channel)
325  {
326  case RED:
327  return operator()( row, col ).r;
328  case GREEN:
329  return operator()( row, col ).g;
330  case BLUE:
331  return operator()( row, col ).b;
332  default:
333  throw std::out_of_range("Invalid channel");
334  }
335  }
336 
342  float operator()(int row, int col, int channel) const
343  {
344  switch(channel)
345  {
346  case RED:
347  return operator()( row, col ).r;
348  case GREEN:
349  return operator()( row, col ).g;
350  case BLUE:
351  return operator()( row, col ).b;
352  default:
353  throw std::out_of_range("Invalid channel");
354  }
355  }
356 
361  Pixel_type& operator()( int row, int col )
362  {
363  return m_image -> pixels[ row ][ col ];
364  }
365 
370  const Pixel_type& operator()( int row, int col ) const
371  {
372  return m_image -> pixels[ row ][ col ];
373  }
374 
376  Pixel_type& operator()( int index )
377  {
378  int row, col;
379  compute_row_col( index, &row, &col );
380  return operator()( row, col );
381  }
382 
384  const Pixel_type& operator()( int index ) const;
385 
388  void invert();
389 
393  {
394  return kjb::get_inverted(*this);
395  }
396 
400  Matrix get_channel(int index) const;
401 
406  void check_bounds( int row, int col ) const;
407 
408 
413  float& at(int row, int col, int channel);
419  float at(int row, int col, int channel) const;
420 
426  Pixel_type& at( int row, int col );
427 
433  const Pixel_type& at( int row, int col ) const;
434 
438  const Pixel_type& at( int index ) const;
439 
443  Pixel_type& at( int index );
444 
446  const Impl_type* c_ptr() const;
447 
453  {
454  return m_image;
455  }
456 
466  void set_c_ptr(Impl_type * iimage)
467  {
468 #ifdef YES_WE_WANT_GARBAGE_POLICE
469  fprintf( stderr, "DTOR: %s\n", info.c_str() );
470  --live_object_counter;
471 #endif
472 
473  kjb_c::kjb_free_image(m_image);
474  m_image = iimage;
475  }
476 
479  Matrix to_grayscale_matrix() const;
480 
494  Matrix to_grayscale_matrix(double r_w, double g_w, double b_w) const;
495 
501  Matrix to_channel_matrix(RGB_channel channel) const;
502 
503 
509  Int_matrix to_color_matrix(double scale = 1.0) const;
510 
516  void from_color_matrix(const Int_matrix& m);
517 
524  void from_color_matrices(
525  const Matrix& red,
526  const Matrix& green,
527  const Matrix& blue
528  );
529 
537  template<class InputIterator>
538  Vector intensity_histogram(InputIterator first, InputIterator last) const;
539 
547  void draw_point(
548  int row,
549  int col,
550  int width,
551  Pixel_type p
552  );
553 
557  void draw_line_segment(
558  int row_from,
559  int col_from,
560  int row_to,
561  int col_to,
562  int width,
563  Pixel_type p
564  );
565 
573  void draw_arrow
574  (
575  const Vector& src,
576  const Vector& dest,
577  const Image::Pixel_type pixel
578  );
579 
588  template <class Iterator>
590  Iterator begin,
591  Iterator end,
592  int width,
593  Pixel_type p
594  )
595  {
596  typedef typename std::iterator_traits<Iterator>::value_type value_type;
597 // BOOST_CONCEPT_ASSERT((kjb::SimpleVector<value_type>));
598 
599  if(begin == end) return; // empty range
600 
601  Iterator it = begin;
602  Iterator it2 = begin;
603  ++it2;
604  for(; it2 != end; ++it, ++it2)
605  {
606  draw_line_segment((*it)[1], (*it)[0], (*it2)[1], (*it2)[0], width, p);
607  }
608  }
609 
622  void draw_aa_rectangle(
623  int first_row,
624  int first_col,
625  int last_row,
626  int last_col,
627  Pixel_type p
628  );
629 
643  int first_row,
644  int first_col,
645  int last_row,
646  int last_col,
647  Pixel_type p
648  );
649 
658  void draw_circle(
659  int center_row,
660  int center_col,
661  int radius,
662  int line_width,
663  Pixel_type p
664  );
665 
666 
673  void draw_disk(
674  int center_row,
675  int center_col,
676  int radius,
677  Pixel_type p
678  );
679 
680 
688  int draw_text_center(
689  int row,
690  int col,
691  const std::string& text,
692  const std::string& font_file = "times14"
693  );
694 
702  int draw_text_top_left(
703  int row,
704  int col,
705  const std::string& text,
706  const std::string& font_file = "times14"
707  );
708 
728  void draw_image(
729  const kjb_c::KJB_image* overlay,
730  int row = 0,
731  int col = 0,
732  int scale = 1
733  );
734 
736  void draw_image(
737  const Image& overlay,
738  int row = 0,
739  int col = 0,
740  int scale = 1
741  );
742 
756  int display( const std::string& title = std::string() ) const;
757 
759  int get_flags() const
760  {
761  return m_image -> flags;
762  }
763 
765  int set_flags(int new_flags)
766  {
767  int old_flags = m_image -> flags;
768  m_image -> flags = new_flags;
769  return old_flags;
770  }
771 };
772 
776 typedef boost::shared_ptr<Image> Image_ptr;
777 
778 
790 Image scale_image(const Image& i, double factor);
791 
792 
793 
795 
796 inline Image get_inverted(const Image& i)
797 {
798  Image res(i);
799  res.invert();
800  return res;
801 }
802 
803 
804 //---------------------------------------------------------
805 // ARITHMETIC OPERATORS
806 //---------------------------------------------------------
807 
812 inline
813 Image operator*(const Image& op1, double op2)
814 {
815  return Image(op1) *= op2;
816 }
817 
824 inline
825 Image operator/(const Image& op1, double op2)
826 {
827  return Image(op1) /= op2;
828 }
829 
833 inline
834 Image operator+(const Image& op1, const Image& op2)
835 {
836  return Image(op1) += op2;
837 }
838 
842 inline
843 Image operator-(const Image& im1, const Image& im2)
844 {
845  return Image(im1) -= im2;
846 }
847 
848 
851 {
852  i.set_flags(i.get_flags() | HAS_ALPHA_CHANNEL);
853 }
854 
855 
858 {
859  i.set_flags(i.get_flags() & ~HAS_ALPHA_CHANNEL);
860 }
861 
862 
864 inline bool is_transparency_enabled(const Image& i)
865 {
866  return i.get_flags() & HAS_ALPHA_CHANNEL;
867 }
868 
869 
870 //---------------------------------------------------------
871 // IMPLEMENTATION OF TEMPLATE MEMBERS
872 //---------------------------------------------------------
873 
874 template<class InputIterator>
875 Vector Image::intensity_histogram(InputIterator first, InputIterator last) const
876 {
878  Vector hist(static_cast<int>(256), static_cast<double>(get_length() / 256.0));
879 
880  for(; first != last; first++)
881  {
882  int val = static_cast<int>(I(first->first, first->second));
883  hist[val] += 0.7;
884 
885  if(val != 0)
886  {
887  hist[val - 1] += 0.15;
888  }
889 
890  if(val != 255)
891  {
892  hist[val + 1] += 0.15;
893  }
894  }
895 
896  return hist;
897 }
898 
899 
901 
902 } //namespace kjb
903 
904 #endif /*KJB_CPP_IMAGE_H */
int draw_text_center(int row, int col, const std::string &text, const std::string &font_file="times14")
Draw the text on the image.
Definition: i_image.cpp:517
boost::shared_ptr< Image > Image_ptr
Definition: i_image.h:776
Definition for the Matrix class, a thin wrapper on the KJB Matrix struct and its related functionalit...
Matrix to_channel_matrix(RGB_channel channel) const
Convert this image to a single matrix by simple averaging of the pixels.
Definition: i_image.cpp:438
void draw_aa_rectangle(int first_row, int first_col, int last_row, int last_col, Pixel_type p)
Draw a solid, axis-aligned rectangle on the image.
Definition: i_image.cpp:186
This class implements matrices, in the linear-algebra sense, restricted to integer-valued elements...
Definition: l_int_matrix.h:71
const Pixel_type & operator()(int row, int col) const
Rvalue pixel access at given row & column, no bounds-checking. The coordinates are row...
Definition: i_image.h:370
Image & operator*=(double op2)
Multiply this image by a scalar; i.e., scale this image in channel space.
Definition: i_image.cpp:164
Vector intensity_histogram(InputIterator first, InputIterator last) const
Computes the intensity histogram of a region – given by a range of pairs – of this image...
Definition: i_image.h:875
bool is_transparency_enabled(const Image &i)
test the Image flag, returning true if the 'alpha' channel is meaningful.
Definition: i_image.h:864
void from_color_matrix(const Int_matrix &m)
Construct an image from a matrix containing RGBA values. Each element of matrix m is an integer which...
Definition: i_image.cpp:272
int display(const std::string &title=std::string()) const
Show the image and return an image number (for closing later).
Definition: i_image.cpp:559
Definition: i_image.h:140
Definition: i_image.h:140
r
Definition: APPgetLargeConnectedEdges.m:127
Image operator-(const Image &im1, const Image &im2)
Subtract two images.
Definition: i_image.h:843
void draw_line_segment(int row_from, int col_from, int row_to, int col_to, int width, Pixel_type p)
Draw a line segment on the image.
Definition: i_image.cpp:473
static Image create_zero_image(int rows, int cols)
Create an empty image of valid zero pixels, r=g=b=0.
Definition: i_image.h:194
This class implements vectors, in the linear-algebra sense, with real-valued elements.
Definition: m_vector.h:87
kjb_c::Pixel Pixel_type
Definition: i_image.h:80
Image scale_image(const Image &i, double factor)
Scale image size by factor, i.e., enlarge or shrink.
Definition: i_image.cpp:603
int get_length() const
Return the number of elements (pixels) in the image.
Definition: i_image.h:268
Image operator+(const Image &op1, const Image &op2)
Add two images.
Definition: i_image.h:834
virtual ~Image()
Dtor simply wraps kjb_free_image()
Definition: i_image.h:209
Impl_type * m_image
Definition: i_image.h:83
static Image create_initialized_image(int rows, int cols, int r, int g, int b)
Create an empty image with pixels initialized to (r, g, b)
Definition: i_image.cpp:86
Image & operator+=(const Image &op2)
Add an image from this image, in place.
Definition: i_image.cpp:146
void draw_circle(int center_row, int center_col, int radius, int line_width, Pixel_type p)
Draw a circle on the image.
Definition: i_image.cpp:495
const Impl_type * c_ptr() const
Access a pointer to the underlying implementation.
Definition: i_image.cpp:419
Pixel_type & operator()(int row, int col)
Lvalue pixel access at given row & column, no bounds-checking. The coordinates are row...
Definition: i_image.h:361
void draw_point(int row, int col, int width, Pixel_type p)
Draw a point on the image.
Definition: i_image.cpp:455
float operator()(int row, int col, int channel) const
Unchecked access of rvalue at given row, column, and RGB_channel.
Definition: i_image.h:342
float & operator()(int row, int col, int channel)
Unchecked access of lvalue at given row, column, and RGB_channel.
Definition: i_image.h:321
for I
Definition: APPgetLargeConnectedEdges.m:141
Impl_type * non_const_c_ptr() const
Access a pointer to the underlying implementation, use with care.
Definition: i_image.h:452
Image & operator/=(double op2)
Divide this image by a scalar; i.e., scale this image in channel space.
Definition: i_image.cpp:176
int draw_text_top_left(int row, int col, const std::string &text, const std::string &font_file="times14")
Draw the text on the image.
Definition: i_image.cpp:528
Image(int rows=0, int cols=0)
Construct image of specified size, defaults to zero by zero.
Definition: i_image.cpp:35
void invert()
Invert this image; i.e., dark becomes light and vice-versa.
Definition: i_image.cpp:312
kjb_c::KJB_image Impl_type
Definition: i_image.h:79
Image & scale(double factor)
Scale the image by factor using imagemagick (deprecated).
Definition: i_image.h:233
int get_num_rows() const
Return the number of rows in the image.
Definition: i_image.h:256
Image get_inverted(const Image &)
Definition: i_image.h:796
Int_matrix to_color_matrix(double scale=1.0) const
Convert this image to a single matrix containing RGBA values. The first eight least significant bits ...
Definition: i_image.cpp:244
int set_flags(int new_flags)
set "flags" field of underlying KJB_image; return previous flags
Definition: i_image.h:765
void set_c_ptr(Impl_type *iimage)
set this matrix to point to a different c memory, freeing the previously pointed area ...
Definition: i_image.h:466
Definition: i_image.h:140
Pixel_type & operator()(int index)
Access lvalue at row-major index, without bounds-checking.
Definition: i_image.h:376
Image operator/(const Image &op1, double op2)
Scale an image in channel space, yielding a new image.
Definition: i_image.h:825
Matrix to_grayscale_matrix(const Image &i)
Definition: i_image.cpp:598
Matrix get_channel(int index) const
Definition: i_image.cpp:317
void draw_disk(int center_row, int center_col, int radius, Pixel_type p)
draw a disk (a filled circle) on the image, of a given color.
Definition: i_image.cpp:506
void draw_arrow(const Vector &src, const Vector &dest, const Image::Pixel_type pixel)
Draw an arrow from src to dest.
Definition: i_image.cpp:570
void swap(kjb::Gsl_Multimin_fdf &m1, kjb::Gsl_Multimin_fdf &m2)
Swap two wrapped multimin objects.
Definition: gsl_multimin.h:693
void draw_image(const kjb_c::KJB_image *overlay, int row=0, int col=0, int scale=1)
Overlay another image on this image, with an optional offset.
Definition: i_image.cpp:539
#define dest(triedge, pointptr)
Definition: triangle.c:938
Image & crop(int r, int c, int num_rows, int num_cols)
Crop this image.
Definition: i_image.cpp:112
int get_num_cols() const
Return the number of columns in the image.
Definition: i_image.h:262
Matrix to_grayscale_matrix() const
Convert this image to a single matrix by simple averaging of the pixels.
Definition: i_image.cpp:424
float & at(int row, int col, int channel)
Access lvalue of pixel channel at row, column coordinates.
Definition: i_image.cpp:351
Image rgb_matrices_to_image(const Matrix &red_channel, const Matrix &green_channel, const Matrix &blue_channel)
Contruct an image from three matrices representing red, green, blue channels.
Definition: i_image.cpp:626
void draw_aa_rectangle_outline(int first_row, int first_col, int last_row, int last_col, Pixel_type p)
Draw the outline of an, axis-aligned rectangle on the image.
Definition: i_image.cpp:224
Image get_inverted() const
Generate an inverted version of this image (deprecated).
Definition: i_image.h:392
void write(const std::string &fname) const
Write to a file.
Definition: i_image.cpp:106
get the indices of edges in each direction for i
Definition: APPgetLargeConnectedEdges.m:48
void swap(Image &other)
Swap the implementation of two images.
Definition: i_image.h:220
This class implements matrices, in the linear-algebra sense, with real-valued elements.
Definition: m_matrix.h:94
RGB_channel
Constants for accessing color channels via number, with at().
Definition: i_image.h:140
void enable_transparency(Image &i)
set Image flag, to indicate that the 'alpha' channel is meaningful.
Definition: i_image.h:850
for m
Definition: APPgetLargeConnectedEdges.m:64
Wrapped version of the C struct KJB_image.
Definition: i_image.h:76
void from_color_matrices(const Matrix &red, const Matrix &green, const Matrix &blue)
Contruct an image from three matrices representing red, green, blue channels.
Definition: i_image.cpp:445
Image & operator=(const kjb_c::KJB_image &src)
Deep copy assignment from C-type image.
Definition: i_image.cpp:129
void draw_polyline(Iterator begin, Iterator end, int width, Pixel_type p)
Draw a polyline on the image, i.e., a chain of line segments.
Definition: i_image.h:589
Gsl_Vector operator*(double scalar, const Gsl_Vector &vector)
multiply scalar and vector, scalar written on the left side
Definition: gsl_vector.h:661
Definition for the Vector class, a thin wrapper on the KJB Vector struct and its related functionalit...
int get_flags() const
return copy of the "flags" field of underlying KJB_image object
Definition: i_image.h:759
void check_bounds(int row, int col) const
Test whether row, column coordinates are valid.
Definition: i_image.cpp:334
friend void swap(kjb::Image &a, kjb::Image &b)
Definition: i_image.h:226
void disable_transparency(Image &i)
clear Image flag, to indicate that the 'alpha' channel is not meaningful.
Definition: i_image.h:857
Definition: i_image.h:140
Image & operator-=(const Image &op2)
Subtract an image from this image, in place.
Definition: i_image.cpp:153