00001
00002 #include <bgui/bgui_range_adjuster_tableau.h>
00003
00004
00005
00006
00007 #include <vcl_cassert.h>
00008 #include <vcl_cmath.h>
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
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
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
00072 bgui_range_adjuster_tableau::~bgui_range_adjuster_tableau()
00073 {
00074 }
00075
00076
00077 int bgui_range_adjuster_tableau::map_val_to_display(const double val)
00078 {
00079
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
00088 double bgui_range_adjuster_tableau::map_display_to_val(const int display_x)
00089 {
00090
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
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
00117
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
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
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
00229
00230
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
00315 bool bgui_range_adjuster_tableau::handle(const vgui_event& event)
00316 {
00317 if (event.type == vgui_BUTTON_DOWN)
00318 {
00319
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
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
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 }