Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

bgui_range_adjuster_tableau.cxx

Go to the documentation of this file.
00001 // This is brl/bbas/bgui/bgui_range_adjuster_tableau.cxx
00002 #include <bgui/bgui_range_adjuster_tableau.h>
00003 //:
00004 // \file
00005 // \author  J. L. Mundy after Matt Leotta original
00006 
00007 #include <vcl_cassert.h>
00008 #include <vcl_cmath.h> //for fabs()
00009 #include <vil1/vil1_memory_image_of.h>
00010 #include <vil1/vil1_vil.h>
00011 #include <vil/vil_image_resource.h>
00012 #include <vil/vil_image_view.h>
00013 #include <vil/algo/vil_histogram.h>
00014 #include <vil/vil_pixel_traits.h>
00015 #include <vgui/vgui.h>
00016 #include <vgui/vgui_gl.h>
00017 #include <vgui/vgui_find.h>
00018 #include <vgui/vgui_easy2D_tableau.h>
00019 #include <vgui/vgui_range_map_params.h>
00020 #include <vgui/vgui_projection_inspector.h>
00021 
00022 void bgui_range_adjuster_tableau::draw_box()
00023 {
00024   // Draw a square around the histogram
00025   vcl_vector<float> x_corners, y_corners;
00026   x_corners.push_back(left_offset_);
00027   x_corners.push_back(left_offset_+graph_width_);
00028   x_corners.push_back(left_offset_+graph_width_);
00029   x_corners.push_back(left_offset_);
00030   y_corners.push_back(top_offset_);
00031   y_corners.push_back(top_offset_);
00032   y_corners.push_back(top_offset_+graph_height_);
00033   y_corners.push_back(top_offset_+graph_height_);
00034   vgui_soview2D_polygon* sov =
00035     this->add_polygon(4, &x_corners[0], &y_corners[0]);
00036   sov->set_selectable(false);
00037 }
00038 
00039 void bgui_range_adjuster_tableau::init()
00040 {
00041   hardware_ = false;
00042   this->set_foreground(0.8f, 1.0f, 0.0);
00043   this->set_line_width(5.0f);
00044   this->draw_box();
00045 }
00046 
00047 //========================================================================
00048 // Constructors
00049 
00050 bgui_range_adjuster_tableau::bgui_range_adjuster_tableau(const char* n) :
00051   vgui_easy2D_tableau(n), min_bar_(0), max_bar_(0),
00052   left_offset_(10), top_offset_(10),
00053   graph_width_(256), graph_height_(200), plot_(0), hist_(0,0)
00054 {   this->init(); }
00055 
00056 bgui_range_adjuster_tableau::bgui_range_adjuster_tableau(vgui_tableau_sptr const& t,
00057                                                          const char* n) :
00058   vgui_easy2D_tableau(t, n), min_bar_(0), max_bar_(0),
00059   left_offset_(10), top_offset_(10),
00060   graph_width_(256), graph_height_(200), plot_(0), hist_(0,0)
00061 {   this->init(); }
00062 
00063 bgui_range_adjuster_tableau::bgui_range_adjuster_tableau(vgui_image_tableau_sptr const& t,
00064                                                          const char* n) :
00065   vgui_easy2D_tableau(t,n), min_bar_(0), max_bar_(0),
00066   left_offset_(10), top_offset_(10),
00067   graph_width_(256), graph_height_(200), plot_(0), hist_(0,0)
00068 {   this->init(); }
00069 
00070 //========================================================================
00071 // Destructor.
00072 bgui_range_adjuster_tableau::~bgui_range_adjuster_tableau()
00073 {
00074 }
00075 
00076 //:map the data value of histogrammed intensity to display coordinates
00077 int bgui_range_adjuster_tableau::map_val_to_display(const double val)
00078 {
00079   //compute display scale
00080   double scale = 1.0;
00081   if (vcl_fabs(max_-min_)>0)
00082     scale = graph_width_/(max_-min_);
00083   int display_x = (int)((val-min_)*scale + left_offset_);
00084   return display_x;
00085 }
00086 
00087 //:map the data value of histogrammed intensity to display coordinates
00088 double bgui_range_adjuster_tableau::map_display_to_val(const int display_x)
00089 {
00090   //compute display scale
00091   double scale = 1.0;
00092   if (vcl_fabs(max_-min_)>0)
00093     scale = graph_width_/(max_-min_);
00094   double temp = display_x - left_offset_;
00095   temp/=scale;
00096   return temp + min_;
00097 }
00098 
00099 //:draw stretch bars
00100 void bgui_range_adjuster_tableau::draw_stretch_bars()
00101 {
00102   double temp = hist_.value_with_area_below(0.1);
00103   int min_pos = this->map_val_to_display(temp);
00104   temp = hist_.value_with_area_above(0.1);
00105   int max_pos = this->map_val_to_display(temp);
00106   this->set_foreground(0.0, 1.0, 0);
00107   min_bar_ =
00108     this->add_line(min_pos, top_offset_, min_pos, graph_height_+top_offset_);
00109   max_bar_ =
00110     this->add_line(max_pos, top_offset_, max_pos, graph_height_+top_offset_);
00111   this->set_foreground(1.0, 1.0, 0);
00112   min_bar_->set_selectable(false);
00113   max_bar_->set_selectable(false);
00114 }
00115 
00116 //: Update the histogram from image resource.
00117 //  Currently handle a few useful cases
00118 bool bgui_range_adjuster_tableau::update(vil_image_resource_sptr const& r)
00119 {
00120   data_.clear();
00121   unsigned np = r->nplanes();
00122   vil_pixel_format f = r->pixel_format();
00123   vil_pixel_format type = vil_pixel_format_component_format(f);
00124   switch (type )
00125   {
00126    case VIL_PIXEL_FORMAT_BYTE: {
00127     vil_image_view<vxl_byte> v = r->get_view();
00128     assert(v);
00129     min_ = vil_pixel_traits<vxl_byte>::minval();
00130     max_ = vil_pixel_traits<vxl_byte>::maxval();
00131     vil_histogram_byte(v , data_);
00132     break; }
00133    case VIL_PIXEL_FORMAT_SBYTE: {
00134     vil_image_view<vxl_sbyte> v = r->get_view();
00135     assert(v);
00136     min_ = vil_pixel_traits<vxl_sbyte>::minval();
00137     max_ = vil_pixel_traits<vxl_sbyte>::maxval();
00138     vil_histogram(v, data_, min_, max_, graph_width_);
00139     hardware_ = false;
00140     break; }
00141    case VIL_PIXEL_FORMAT_UINT_16: {
00142     vil_image_view<vxl_uint_16> v = r->get_view();
00143     assert(v);
00144     min_ = vil_pixel_traits<vxl_uint_16>::minval();
00145     max_ = vil_pixel_traits<vxl_uint_16>::maxval();
00146     vil_histogram(v, data_, min_, max_, graph_width_);
00147     hardware_ = np==1;
00148     break; }
00149    case VIL_PIXEL_FORMAT_INT_16: {
00150     vil_image_view<vxl_int_16> v = r->get_view();
00151     assert(v);
00152     min_ = vil_pixel_traits<vxl_int_16>::minval();
00153     max_ = vil_pixel_traits<vxl_int_16>::maxval();
00154     vil_histogram(v, data_, min_, max_, graph_width_);
00155     hardware_ = false;
00156     break; }
00157    case VIL_PIXEL_FORMAT_FLOAT: {
00158     vil_image_view<float> v = r->get_view();
00159     assert(v);
00160     min_ = vil_pixel_traits<float>::minval();
00161     max_ = vil_pixel_traits<float>::maxval();
00162     vil_histogram(v, data_, min_, max_, graph_width_);
00163     hardware_ = false;
00164     break; }
00165    case VIL_PIXEL_FORMAT_DOUBLE: {
00166     vil_image_view<double> v = r->get_view();
00167     assert(v);
00168     min_ = vil_pixel_traits<double>::minval();
00169     max_ = vil_pixel_traits<double>::maxval();
00170     vil_histogram(v, data_, min_, max_, graph_width_);
00171     hardware_ = false;
00172     break; }
00173    default:
00174     vcl_cout << "In bgui_range_adjuster_tableau - image type not supported\n";
00175     return false;
00176   }
00177   hist_ = bsta_histogram<double>(min_, max_, data_);
00178   this->draw_histogram();
00179   this->draw_stretch_bars();
00180   return true;
00181 }
00182 
00183 //: update from child
00184 bool bgui_range_adjuster_tableau::update()
00185 {
00186   vgui_image_tableau_sptr itab = this->get_child_image_tableau();
00187   if (!itab)
00188     return false;
00189   vil_image_resource_sptr image = itab->get_image_resource();
00190   return this->update(image);
00191 }
00192 
00193 bool bgui_range_adjuster_tableau::update(const double min, const double max,
00194                                          vcl_vector<double> const& hist)
00195 {
00196   if (!hist.size())
00197     return false;
00198   min_ = min;
00199   max_ = max;
00200   data_ = hist;
00201   hist_ = bsta_histogram<double>(min, max, data_);
00202   this->draw_histogram();
00203   this->draw_stretch_bars();
00204   return true;
00205 }
00206 
00207 bool bgui_range_adjuster_tableau::update(vil1_memory_image_of< vil1_rgb<unsigned char> >& img)
00208 {
00209   vil_image_resource_sptr image = vil1_to_vil_image_resource(img);
00210   return this->update();
00211 }
00212 
00213 void bgui_range_adjuster_tableau::draw_histogram()
00214 {
00215   double max = data_[0];
00216   for (unsigned int i=1; i<data_.size(); ++i)
00217     if (max < data_[i]) max = data_[i];
00218 
00219   // scale and shift the data points
00220   vcl_vector<float> xscaled, yscaled;
00221   for (unsigned int i=0; i<data_.size(); ++i) {
00222     xscaled.push_back(left_offset_ + i);
00223     yscaled.push_back(top_offset_ + graph_height_ - data_[i]/max*graph_height_);
00224   }
00225 
00226   if (plot_)
00227   {
00228     // Update the plot points
00229     // This is a bit more efficient that deleting and reconstructing
00230     //   but not as "clean"
00231     for (unsigned int i=0; i<xscaled.size(); ++i) {
00232       plot_->x[i] = xscaled[i];
00233       plot_->y[i] = yscaled[i];
00234     }
00235   }
00236   else
00237   {
00238     plot_ = this->add_linestrip(xscaled.size(), &xscaled[0], &yscaled[0]);
00239     plot_->set_selectable(false);
00240   }
00241   this->post_redraw();
00242 }
00243 
00244 vgui_image_tableau_sptr bgui_range_adjuster_tableau::get_child_image_tableau()
00245 {
00246   vgui_tableau_sptr ch = this->get_child(0);
00247   if (ch)
00248   {
00249     vgui_image_tableau_sptr itab;
00250     itab.vertical_cast(vgui_find_below_by_type_name(ch, vcl_string("vgui_image_tableau")));
00251     return itab;
00252   }
00253   else
00254     return 0;
00255 }
00256 
00257 float bgui_range_adjuster_tableau::screen_to_bar(const float sx)
00258 {
00259   return  sx + left_offset_;
00260 }
00261 
00262 float bgui_range_adjuster_tableau::bar_to_screen(const float bx)
00263 {
00264   return bx - left_offset_;
00265 }
00266 
00267 
00268 void bgui_range_adjuster_tableau::adjust_min_bar(const float x)
00269 {
00270   if (!(min_bar_&&max_bar_))
00271     return;
00272   float xb = screen_to_bar(x);
00273   float xmax = max_bar_->x0;
00274   if (xb<0)
00275   {
00276     min_bar_->x0=0;
00277     min_bar_->x1=0;
00278     return;
00279   }
00280   if (x>xmax)
00281   {
00282     min_bar_->x0=xmax;
00283     min_bar_->x1=xmax;
00284     return;
00285   }
00286   min_bar_->x0 = xb;
00287   min_bar_->x1 = xb;
00288 }
00289 
00290 void bgui_range_adjuster_tableau::adjust_max_bar(const float x)
00291 {
00292   if (!(min_bar_&&max_bar_))
00293     return;
00294   float xb = screen_to_bar(x);
00295   float xl = screen_to_bar(graph_width_);
00296   float xmin = min_bar_->x0;
00297   if (xb>xl)
00298   {
00299     max_bar_->x0=xl;
00300     max_bar_->x1=xl;
00301     return;
00302   }
00303   if (x<xmin)
00304   {
00305     max_bar_->x0=xmin;
00306     max_bar_->x1=xmin;
00307     return;
00308   }
00309   max_bar_->x0 = xb;
00310   max_bar_->x1 = xb;
00311 }
00312 
00313 //========================================================================
00314 //: Handles all events for this tableau.
00315 bool bgui_range_adjuster_tableau::handle(const vgui_event& event)
00316 {
00317   if (event.type == vgui_BUTTON_DOWN)
00318   {
00319     //Adjust the stretch bars
00320     float pointx, pointy;
00321     vgui_projection_inspector p_insp;
00322     p_insp.window_to_image_coordinates(event.wx, event.wy, pointx, pointy);
00323     float min_pos = 0, max_pos = 0, y = 0;
00324     if (event.modifier == vgui_SHIFT)
00325       this->adjust_max_bar(pointx);
00326     else
00327       this->adjust_min_bar(pointx);
00328 
00329     //Use the bar positions to set the range map max min values.
00330     if (min_bar_)
00331       min_bar_->get_centroid(&min_pos, &y);
00332     if (max_bar_)
00333       max_bar_->get_centroid(&max_pos, &y);
00334 
00335     double min_val = map_display_to_val((int)min_pos);
00336     double max_val = map_display_to_val((int)max_pos);
00337     if (min_val>max_val)
00338       return vgui_easy2D_tableau::handle(event);
00339 
00340     vgui_image_tableau_sptr child = this->get_child_image_tableau();
00341     if (!child)
00342       return vgui_easy2D_tableau::handle(event);
00343 
00344     vil_image_resource_sptr r = child->get_image_resource();
00345     if (!r)
00346       return vgui_easy2D_tableau::handle(event);
00347     //If the image can be hardware mapped, it uses glPixelMap* operations
00348     vgui_range_map_params_sptr rmp;
00349     if (r->nplanes()==1)
00350       rmp = new vgui_range_map_params(min_val,max_val, 1.0f,
00351                                       false, hardware_, hardware_);
00352     else if (r->nplanes()==3)
00353       rmp = new vgui_range_map_params(min_val,max_val, min_val, max_val,
00354                                       min_val, max_val,1.0f, 1.0f, 1.0f,
00355                                       false, hardware_, hardware_);
00356     else
00357       return vgui_easy2D_tableau::handle(event);
00358 
00359     child->set_mapping(rmp);
00360   }
00361   return vgui_easy2D_tableau::handle(event);
00362 }
00363 
00364 
00365 void bgui_range_adjuster_tableau::clear()
00366 {
00367   this->remove(plot_);
00368   delete plot_;
00369   plot_ = 0;
00370   this->post_redraw();
00371 }

Generated on Thu Jan 10 14:52:11 2008 for contrib/brl/bbas/bgui by  doxygen 1.4.4