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