Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
HistoImageCanvas.cpp
1 #include "HistoImageCanvas.hh"
2 
3 #include <Gui/StringConv.hh>
4 
5 #include <wx/dcbuffer.h>
6 
7 using namespace BIAS;
8 using namespace std;
9 
10 
13  wxStatusBar *sbar, int sbarid,
14  wxWindowID id,
15  const wxPoint& pos,
16  const wxSize& size,
17  long style,
18  const wxString& name)
19  : wxPanel(parent, id, pos, size, style, name)
20 {
21  SetMinSize(wxSize(294, 219));
22 
23 // cout << "SIZE OF HISTOCANVAS INPUT " <<size.GetWidth()
24 // << "x" << size.GetHeight() << endl;
25 
26  //default values
27  histo_float_steps = 256;
28  histo_type = -1;
29  histo_channels = 0;
30 
31  histo_float_min = 0.0;
32  histo_float_step = 0.0;
33 
34  //Pointer to the main statusbar in the histoframe
35  SBar_ = sbar;
36  //# of the field in the statusbar to be filled with histogramm-value
37  SBarID_=sbarid;
38 
39  //Histogramm is shown 1step/1pxl (1xhistogramm)
40  // also available 2xZoom (1step/2pxl),
41  // 3xZoom and
42  // 4xZoom
43  histoZoom_ = 1;
44 
45  //sometimes in WIN it doesn't repaint the canvas after initializing it
46  wxPaintEvent ev;
47  OnPaint(ev);
48 }
49 
50 
53 {}
54 
55 
56 BEGIN_EVENT_TABLE (HistoImageCanvas, wxWindow)
57  EVT_MOTION (HistoImageCanvas::OnMouseMove)
58  EVT_LEAVE_WINDOW (HistoImageCanvas::OnMouseLeave)
59  EVT_PAINT (HistoImageCanvas::OnPaint)
60  //EVT_MOTION (HistoImageCanvas::OnMouseMove)
61  //EVT_CHAR (HistoFrame::OnKey)
62  EVT_SIZE (HistoImageCanvas::OnResize)
63  //EVT_LEAVE_WINDOW(HistoImageCanvas::OnMouseLeave)
64 END_EVENT_TABLE()
65 
66 
67 void HistoImageCanvas::
68 OnMouseLeave(wxMouseEvent&)
69 {
70  if (SBar_){ SBar_->SetStatusText(wxT(""), SBarID_); }
71  mousex_=mousey_=0;
72 }
73 
74 
76 OnMouseMove(wxMouseEvent &event)
77 {
78  wxClientDC dc(this);
79  PrepareDC(dc);
80  wxPoint pos = event.GetPosition();
81  mousex_ = dc.DeviceToLogicalX( pos.x );
82  mousey_ = dc.DeviceToLogicalY( pos.y );
83  UpdateStatusBar((unsigned) mousex_, (unsigned) mousey_);
84 }
85 
86 
88 UpdateStatusBar(unsigned mouseX, unsigned mouseY)
89 {
90  wxPoint pos = GetPosition();
91  // compute original coordinate for HistoImageCanvas canvas
92  int ix=(int)mouseX-(int)pos.x;
93  int iy=(int)mouseY-(int)pos.y;
94 
95  wxSize sz = GetClientSize();
96  int hei = sz.y;
97 #ifdef WIN32
98  //fixing some strange bug in windows when painting things
99  hei-=40;
100  ix+=2;
101 #endif
102 
103  int slice = (int)((hei-20)/histo_channels);
104 
105  ostringstream os;
106  int cur_step = (int)((ix-10)/histoZoom_);
107  int cur_channel = (int)((iy-10)/slice);
108 
109  if(cur_channel>=0 && cur_channel<histo_channels){
110  if(histo_type == 0 && cur_step>=0 && cur_step<256){
111  os << "UnsignedChar (Channel " << cur_channel
112  << ") - Value " << cur_step
113  << " (" << 100.0*histo_percentage [cur_channel][cur_step]
114  << "% Total)";
115  }
116  else if(histo_type == 1 && cur_step>=0 && cur_step<histo_float_steps &&
117  histo_float_step != 0.0){
118  os << "Float (Channel " << cur_channel
119  << ") - Value " << histo_float_step*(float)cur_step + histo_float_min
120  << " to " << histo_float_step*((float)cur_step+1.0) + histo_float_min
121  << " (" << 100.0*histo_percentage [cur_channel][cur_step]
122  << "% Total)";
123  }
124  }
125 
126  //display Histogramm value:
127  SBar_->SetStatusText(AsciiToWx(os.str()), SBarID_);
128 }
129 
130 
131 //CALCULATE HISTOGRAMM OF CURRENT IMAGE
134 
135  histo_size = image.GetWidth()*image.GetHeight();
136 
137  //little pixelsum-check
138  if(histo_size <= 0)
139  BIASERR("No image for HISTOGRAMMS presented!");
140 
142  if(histo_channels<=0 || histo_channels>=9){
143  cout << "Invalid amount of channels (allowed only 1, 2, 3, ..., 8 "
144  << "channels in the image" << endl;
145  histo_type = -1;
146  histo_channels = 0;
147  return;
148  }
149 
150  //preaparations
151  histo_percentage.clear();
152  histo_percentage_biggest.clear();
153 
154  std::vector<float> dummy_percentage;
155 
156  histo_type = -1;
157  switch (image.GetStorageType()){
159  {
160  //debug-message
161  //cout << "UNSIGNED CHAR" << endl;
162 
163  histo_type = 0;
164 
165  histo_UC.clear();
166 
167  //preparations
168  std::vector<int> dummy;
169  for (int i = 0; i < histo_channels; i++){
170  dummy.clear();
171  dummy_percentage.clear();
172  for (int j = 0; j < 256; j++){
173  dummy.push_back(0);
174  dummy_percentage.push_back(0.0);
175  }
176  histo_UC.push_back(dummy);
177  histo_percentage.push_back(dummy_percentage);
178 
179  histo_percentage_biggest.push_back(0.0);
180  }
181 
182  //compute histogramm
183  unsigned char* data = (unsigned char*)image.GetImageData();
184 
185  int index;
186 
187  //HISTOGRAMM FOR PLANAR IMAGES
188  index = 0;
189  if(image.IsPlanar()){
190  for(int i = 0; i < histo_channels; i++){
191  for(int j = 0; j < histo_size; j++){
192  histo_UC[i][(int)data[index]]++;
193  index++;
194  }
195  }
196  }
197  //HISTOGRAMM FOR INTERLEAVED IMAGES
198  else if(image.IsInterleaved()){
199  for(int j = 0; j < histo_size; j++){
200  for(int i = 0; i < histo_channels; i++){
201  histo_UC[i][(int)data[index]]++;
202  index++;
203  }
204  }
205  }
206 
207  //filling percentages and giving debug info out
208 
209  for(int i = 0; i < histo_channels; i++){
210  float sum = 0.0;
211  // cout << "CHANNEL " << i << ":" << endl << endl;
212  for (int j = 0; j < 256; j++){
213  float perc = (float)histo_UC[i][j]/(float)histo_size;
214  histo_percentage[i][j] = perc;
215  sum += perc;
216 
217  if(perc > histo_percentage_biggest[i])
218  histo_percentage_biggest[i] = perc;
219  }
220  }
221  break;
222  }
223 
224  case ImageBase::ST_float:
225  {
226  //debug-message
227  // cout << "FLOAT" << endl;
228 
229  //TO-DO (probably) - enable float-histo for any number of steps,
230  // not only 256 as it is right now
231  histo_float_steps = 256;
232  //histo_float_steps = GetClientSize().x;
233 
234  histo_type = 1;
235 
236  histo_float.clear();
237 
238  //preparations
239  std::vector<Histo_Entry_Float> dummy;
240  for (int i = 0; i < histo_channels; i++){
241  dummy.clear();
242  dummy_percentage.clear();
243  for (int j = 0; j < histo_float_steps; j++){
244  Histo_Entry_Float dummy_content;
245  dummy_content.value_count = 0;
246 
247  dummy.push_back(dummy_content);
248  dummy_percentage.push_back(0.0);
249  }
250  histo_float.push_back(dummy);
251  histo_percentage.push_back(dummy_percentage);
252 
253  histo_percentage_biggest.push_back(0.0);
254  }
255 
256  float* data = (float*)image.GetImageData();
257 
258  //get min and max-values in the image and compute scale-step
259  float min = 100000.0;
260  float max = -100000.0;
261 
262  for (int i = 0; i < histo_size; i++){
263  if((float)data[i] > max){
264  max = (float)data[i];
265  // int x = (int)(i/image.GetWidth());
266  // int y = i - x*image.GetWidth();
267  //cout << "max (" << y << ", " << x << ") value: " << max << endl;
268  }
269  if((float)data[i] < min)
270  min = (float)data[i];
271  }
272 
273  if(min >= 100000.0 || max <= -100000.0)
274  BIASERR("Image has only pixels above 10^5 values or under -10^5");
275 
276  float step = (max-min)/histo_float_steps;
277 
278  histo_float_min = min;
279  histo_float_step = step;
280 
281  //compute histogramm
282 
283  //FOR PLANAR FLOAT-IMAGES
284  if(image.IsPlanar()){
285  for (int i = 0; i < histo_channels; i++){
286  for (int j = 0; j < histo_size; j++){
287 
288  int index = 0;
289  if(step != 0.0){
290  index = (int)(((float)data[j]-min)/step);
291  }
292 
293  //---COMPUTING HISTOGRAMM---
294  //correcting slight errors while doing it with float-images
295  if(index == histo_float_steps)
296  index--;
297  else if(index == -1)
298  index = 0;
299  //if the float-error is too big while counting histogramm
300  else if(index < -1 || index > histo_float_steps){
301 // cout << "BAD pixel for histogramm: " << endl;
302 // cout << "data[j]: " << data[j]
303 // << " min-data: " << min
304 // << " max-data: " << max
305 // << " index: " << index << endl;
306  BIASERR("HISTOGRAMM IS WRONG, maybe TOO MANY STEPS/TOO WIDE RANGE");
307  }
308  //--------------------------
309 
310  histo_float[i][index].value_count++;
311  }
312  }
313  }
314  //FOR INTERLEAVED IMAGES
315  else if(image.IsInterleaved()){
316  for (int j = 0; j < histo_size; j++){
317  for (int i = 0; i < histo_channels; i++){
318 
319  int index = 0;
320  if(step != 0.0){
321  index = (int)(((float)data[j]-min)/step);
322  }
323 
324  if(index == histo_float_steps)
325  index--;
326  else if(index == -1)
327  index = 0;
328  else if(index < -1 || index > histo_float_steps){
329 // cout << "BAD pixel for histogramm: " << endl;
330 // cout << "data[j]: " << data[j]
331 // << " min-data: " << min
332 // << " max-data: " << max
333 // << " index: " << index << endl;
334  BIASERR("HISTOGRAMM IS WRONG, maybe TOO MANY STEPS/TOO WIDE RANGE");
335  }
336 
337  histo_float[i][index].value_count++;
338  }
339  }
340  }
341 
342  for (int i = 0; i < histo_channels; i++){
343 
344  //cout << "CHANNEL " << i << ":" << endl << endl;
345 
346  //filling percentages and giving debug info out
347  float sum = 0.0;
348  float begin = min;
349  float end = min + step;
350  for (int j = 0; j < histo_float_steps; j++){
351  histo_float[i][j].value_begin = begin;
352  histo_float[i][j].value_end = end;
353 
354  if(begin <= 0.0 && end >= 0.0){
355  histo_float_zero = j;
356  }
357 
358  begin += step; end += step;
359 
360  float perc = (float)histo_float[i][j].value_count/(float)histo_size;
361  histo_percentage[i][j] = perc;
362  sum += perc;
363 
364  if(perc > histo_percentage_biggest[i])
365  histo_percentage_biggest[i] = perc;
366  }
367 // cout << sum*100 << "% total" << endl;
368 // cout << histo_float_steps << " steps in float-histogramm used" << endl;
369  }
370  break;
371  }
372 
373  default:
374  break;
375  }
376 
377  //cout << "HISTOGRAMM UPDATED" << endl;
378 
379  wxPaintEvent ev;
380  OnPaint(ev);
381 
382  //Testing if the statusbar is correctly shown and enabled
383 #ifdef WIN32
384  Refresh();
385 #endif
386 }
387 
388 
389 //Paints Histogramm in HistoFrame, channel after channel
390 //(ordered from upper side of the frame to the bottom:
391 // channel 0,
392 // channel 1,
393 // ...)
395 OnPaint(wxPaintEvent& event){
396  //prepare painter and get size of the window
397  wxBufferedPaintDC dc(this);
398  wxSize sz = GetClientSize();
399  int wid = sz.x;
400  int hei = sz.y;
401  //cout << wid << "; " << hei << endl;
402 
403  //CLEAR
404  dc.SetPen(*wxGREY_PEN);
405  dc.SetBrush(*wxGREY_BRUSH);
406 
407  wxRect rectToDraw(0, 0, wid, hei);
408  //wxRect rectToDraw(4, 4, wid-8, hei-8);
409  dc.DrawRectangle(rectToDraw);
410 
411  dc.SetPen(*wxWHITE_PEN);
412  dc.SetBrush(*wxWHITE_BRUSH);
413 
414  //---------CONFIGURE PARAMETERS OF HISTOGRAMM------
415  wxCoord h;
416  histoZoom_ = 1;
417 
418  //paint original histogramm
419  if(wid <= 512+16)
420  histoZoom_=1;
421  //paint 2xhistogramm
422  else if(wid <= 768+16)
423  histoZoom_=2;
424  //paint 3xhistogramm
425  else if(wid <= 1024+16)
426  histoZoom_=3;
427  //paint 4xhistogramm
428  else
429  histoZoom_=4;
430 
431 #ifdef WIN32
432  //fixing some strange bug in windows when painting things
433  hei-=40;
434 #endif
435  //-------------------------------------------------
436 
437  wxRect rectToDraw2(6, 6, 256*histoZoom_+4, hei-12);
438  //wxRect rectToDraw2(7, 7, wid-14, hei-14);
439  dc.DrawRectangle(rectToDraw2);
440 
441  dc.SetPen(*wxLIGHT_GREY_PEN);
442  dc.SetBrush(*wxLIGHT_GREY_BRUSH);
443 
444  int slice = (int)
445  ((float)(hei-16-(histo_channels-1)*2)/float(histo_channels));
446 
447  for(int i=0; i<histo_channels; i++){
448  wxRect rectToDraw3(8, hei-8-(2+slice)*i-slice,
449  histoZoom_*256, slice);
450  dc.DrawRectangle(rectToDraw3);
451  }
452 
453  //-----
454 
455  dc.SetPen(*wxBLACK_PEN);
456  dc.SetBrush(*wxBLACK_BRUSH);
457 
458  int end = 0;
459 
460  //CRITICAL: if the picture is too wide (looks bad) or
461  // not as wide as 256 pixels -> no histo
462  if(histo_type == 0){
463  end = 256;
464 // cout << "Painting " << histoZoom_
465 // << "xHistogramm for unsigned-char image" << endl;
466  }
467  if(histo_type == 1){
468  //for future flexible resizeable float-histogramm
469  //(not only 1x, 2x, 3x, 4x versions of the same one
470  end = histo_float_steps;
471 // cout << "Painting " << histoZoom_
472 // << "xHistogramm for float image" << endl;
473  }
474 
475  for(int i=0; i<histo_channels; i++){
476  for(int j = 0; j < end; j++){
477  h = (int)(((float)slice)*
479  wxRect rectToDraw(histoZoom_*j+8,
480  hei-h-8-(histo_channels-i-1)*(slice+2),
481  histoZoom_,
482  h);
483  dc.DrawRectangle(rectToDraw);
484  }
485  }
486 }
487 
488 
491  wxSize sz = GetClientSize();
492  int wid = sz.x;
493  int hei = sz.y;
494  cout << "RESIZED-1 TO " << wid << ", " << hei << endl << endl;
495 }
496 
497 
500  UpdateHistogramm(im);
501 }
502 
503 
505 SameName(wxString name, bool settothenewone){
506  if(histo_name != name){
507  if(settothenewone)
508  histo_name = name;
509  return false;
510  }
511  return true;
512 }
513 
514 
516 OnResize(wxSizeEvent & event){
517  wxPaintEvent ev;
518  OnPaint(ev);
519 }
bool SameName(wxString name, bool settothenewone)
std::vector< std::vector< Histo_Entry_Float > > histo_float
void UpdateHistogramm(ImageBase image)
wxString AsciiToWx(const char *thestring)
Converts a C string to a wxString.
Definition: StringConv.hh:32
bool IsInterleaved() const
Definition: ImageBase.hh:491
int value_count
std::vector< std::vector< int > > histo_UC
float image storage type
Definition: ImageBase.hh:118
bool IsPlanar() const
Definition: ImageBase.hh:484
It&#39;s a Canvas used to compute Histogram for current image working.
void UpdateStatusBar(unsigned mouseX, unsigned mouseY)
HistoImageCanvas(wxWindow *parent, wxStatusBar *sbar=NULL, int sbarid=0, wxWindowID id=-1, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(272, 216), long style=wxTAB_TRAVERSAL, const wxString &name=wxT("HistoImageCanvas"))
unsigned int GetWidth() const
Definition: ImageBase.hh:312
void OnPaint(wxPaintEvent &event)
const void * GetImageData() const
Definition: ImageBase.hh:280
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
unsigned int GetHeight() const
Definition: ImageBase.hh:319
std::vector< float > histo_percentage_biggest
enum EStorageType GetStorageType() const
Definition: ImageBase.hh:414
(8bit) unsigned char image storage type
Definition: ImageBase.hh:112
void OnMouseMove(wxMouseEvent &event)
void NewImage(BIAS::ImageBase &im)
std::vector< std::vector< float > > histo_percentage
This is the base class for images in BIAS.
Definition: ImageBase.hh:102
void OnResize(wxSizeEvent &event)