00001
00002 #include "vgui_vil_image_renderer.h"
00003
00004
00005
00006
00007
00008
00009
00010 #include <vcl_iostream.h>
00011 #include <vcl_cmath.h>
00012 #include <vul/vul_timer.h>
00013 #include <vil/vil_property.h>
00014 #include <vil/vil_image_resource.h>
00015 #include <vil/vil_pyramid_image_resource.h>
00016 #include <vil/vil_image_view.h>
00017 #include <vil/vil_new.h>
00018 #include <vgui/vgui_section_render.h>
00019 #include "vgui_gl.h"
00020 #include "vgui_macro.h"
00021 #include "vgui_section_buffer.h"
00022 #include "vgui_range_map.h"
00023
00024
00025 static const bool debug = false;
00026 #define trace if (true) { } else vcl_cerr
00027
00028
00029
00030 static const unsigned buf_limit = 25000000;
00031
00032 vgui_vil_image_renderer::
00033 vgui_vil_image_renderer()
00034 : buffer_( 0 ), buffer_params_(0), valid_buffer_(false),
00035 x0_(0), y0_(0), w_(1), h_(1), zx_(1.0f), zy_(1.0f), sni_(0), snj_(0)
00036 {
00037 }
00038
00039
00040 vgui_vil_image_renderer::
00041 ~vgui_vil_image_renderer()
00042 {
00043 delete buffer_;
00044 }
00045
00046 void
00047 vgui_vil_image_renderer::
00048 set_image_resource( vil_image_resource_sptr const& image )
00049 {
00050
00051 delete buffer_;
00052 buffer_ = 0;
00053 valid_buffer_ = false;
00054 the_image_ = image;
00055 if ( the_image_ ) {
00056 trace << "image : " << the_image_ << vcl_flush;
00057 }
00058 }
00059
00060
00061 vil_image_resource_sptr
00062 vgui_vil_image_renderer::
00063 get_image_resource() const
00064 {
00065 return the_image_;
00066 }
00067
00068
00069 void
00070 vgui_vil_image_renderer::
00071 reread_image()
00072 {
00073 delete buffer_;
00074 buffer_ = 0;
00075 valid_buffer_ = false;
00076 }
00077
00078 void vgui_vil_image_renderer::
00079 create_buffer(vgui_range_map_params_sptr const& rmp)
00080 {
00081 delete buffer_;
00082 unsigned ni = the_image_->ni(), nj = the_image_->nj();
00083
00084
00085 unsigned dims =
00086 static_cast<unsigned>(vcl_sqrt(static_cast<double>(buf_limit)));
00087 if (ni*nj>buf_limit)
00088 {
00089 vcl_cerr << "In vgui_vil_image_renderer - image too large, " << ni << 'x' << nj <<", for complete buffer.\n"
00090 << "Rendering only the top left "<< dims << 'x' << dims << " corner\n";
00091 unsigned dims =
00092 static_cast<unsigned>(vcl_sqrt(static_cast<double>(buf_limit)));
00093 if (ni<dims)
00094 nj = (buf_limit/ni) -1 ;
00095 else {ni=dims; nj = dims;}
00096 if (nj<dims)
00097 ni = (buf_limit/nj) -1 ;
00098 else {ni=dims; nj = dims;}
00099 }
00100 buffer_ = new vgui_section_buffer( 0, 0, ni, nj, GL_NONE, GL_NONE );
00101 buffer_->apply( the_image_, rmp );
00102
00103 buffer_params_ = rmp;
00104 valid_buffer_ = true;
00105 }
00106
00107 void vgui_vil_image_renderer::
00108 create_buffer(vgui_range_map_params_sptr const& rmp,
00109 unsigned x0, unsigned y0, unsigned x1, unsigned y1,
00110 float zoomx, float zoomy)
00111 {
00112 delete buffer_;
00113 buffer_ = new vgui_section_buffer( x0, y0, x1, y1, GL_NONE, GL_NONE );
00114 buffer_->set_zoom(zoomx, zoomy);
00115 buffer_->apply( the_image_, rmp );
00116
00117 buffer_params_ = rmp;
00118 valid_buffer_ = true;
00119 }
00120
00121 void vgui_vil_image_renderer::
00122 create_buffer(vgui_range_map_params_sptr const& rmp,
00123 float zoomx, float zoomy,
00124 vil_image_resource_sptr const& ir)
00125 {
00126 delete buffer_;
00127 buffer_ = 0;
00128 if (!rmp||!ir)
00129 return;
00130
00131 buffer_ = new vgui_section_buffer( 0, 0,
00132 ir->ni(), ir->nj(),
00133 GL_NONE, GL_NONE );
00134 buffer_->set_zoom(zoomx, zoomy);
00135 buffer_->apply( ir, rmp );
00136
00137 buffer_params_ = rmp;
00138 valid_buffer_ = true;
00139 }
00140
00141 void vgui_vil_image_renderer::
00142 draw_pixels()
00143 {
00144 buffer_->draw_as_image() || buffer_->draw_as_rectangle();
00145 }
00146
00147
00148 bool vgui_vil_image_renderer::
00149 render_directly(vgui_range_map_params_sptr const& rmp)
00150 {
00151 if (!rmp)
00152 return false;
00153
00154 if (!old_range_map_params(rmp))
00155 valid_buffer_ = false;
00156
00157
00158
00159 if (!the_image_||the_image_->nplanes()!=rmp->n_components_)
00160 return false;
00161
00162
00163 bool hmap = !(rmp->cache_mapped_pix_);
00164
00165
00166 unsigned i0=0, j0=0;
00167 unsigned ni =the_image_->ni(), nj=the_image_->nj();
00168 float zoomx = 1, zoomy = -1;
00169 pixel_view(i0, ni, j0, nj, zoomx, zoomy);
00170
00171
00172
00173 bool vp_changed = false;
00174 if ((x0_ != i0) || (y0_ != j0) || (ni != w_) || (nj != h_) ||
00175 (zx_ != zoomx) || (zy_ != zoomy)) {
00176 vp_changed = true;
00177 x0_ = i0; y0_ = j0; w_ = ni; h_ = nj;
00178 zx_ = zoomx; zy_ = zoomy;
00179 }
00180
00181
00182
00183
00184 float actual_scale = 1.0f;
00185 vil_pyramid_image_resource_sptr pyr;
00186 if (the_image_->get_property(vil_property_pyramid))
00187 pyr = (vil_pyramid_image_resource*)the_image_.ptr();
00188
00189
00190 vul_timer t;
00191
00192
00193
00194
00195
00196
00197 vil_pixel_format format = the_image_->pixel_format();
00198 switch ( format )
00199 {
00200 case VIL_PIXEL_FORMAT_BYTE:
00201 {
00202 vgui_range_map<unsigned char> rm(*rmp);
00203 switch ( the_image_->nplanes() )
00204 {
00205 case 1:
00206 {
00207 vbl_array_1d<float> fLmap = rm.fLmap();
00208 if (!fLmap.size())
00209 return false;
00210 if (vp_changed||(hmap&&!vbuf_)||(!hmap&&!valid_buffer_)){
00211 vil_image_view<unsigned char> view;
00212 if (pyr)
00213 {
00214 view = pyr->get_copy_view(i0, ni, j0, nj, zoomx, actual_scale);
00215 sni_ = view.ni(); snj_ = view.nj();
00216 zx_/=actual_scale; zy_/=actual_scale;
00217 if (hmap)
00218 vbuf_ = view.memory_chunk();
00219 else
00220 {
00221 vil_image_resource_sptr ir =
00222 vil_new_image_resource_of_view(view);
00223 this->create_buffer(rmp, zx_, zy_, ir);
00224 valid_buffer_ = true;
00225 }
00226 }
00227 else if (hmap){
00228 view = the_image_->get_view(i0,ni,j0,nj);
00229 sni_ = view.ni(); snj_ = view.nj();
00230 vbuf_= view.memory_chunk();
00231 } else
00232 this->create_buffer(rmp, i0, j0, ni, nj, zx_, zy_);
00233 }
00234
00235 if (valid_buffer_&&!hmap)
00236 {
00237 buffer_->draw_viewport_as_image();
00238 return true;
00239 }
00240 else
00241 if (vbuf_&&vgui_view_render(vbuf_->data(), sni_, snj_,
00242 zx_, zy_, GL_LUMINANCE,
00243 GL_UNSIGNED_BYTE, hmap, &fLmap))
00244 {
00245 #ifdef RENDER_TIMER
00246 vcl_cout << "Directly Byte Luminance Rendered in "
00247 << t.real() << "msecs\n";
00248 #endif
00249 valid_buffer_ = false;
00250 buffer_params_ = rmp;
00251 return true;
00252 }
00253 return false;
00254 }
00255
00256 case 3:
00257 {
00258 vbl_array_1d<float> fRmap = rm.fRmap();
00259 vbl_array_1d<float> fGmap = rm.fGmap();
00260 vbl_array_1d<float> fBmap = rm.fBmap();
00261 if (!(fRmap.size()&&fGmap.size()&&fBmap.size()))
00262 return false;
00263 if (vp_changed||(hmap&&!vbuf_)||(!hmap&&!valid_buffer_)){
00264 vil_image_view<vil_rgb<unsigned char> > view;
00265 if (pyr)
00266 {
00267 view = pyr->get_copy_view(i0, ni, j0, nj, zoomx, actual_scale);
00268 sni_ = view.ni(); snj_ = view.nj();
00269 zx_/=actual_scale; zy_/=actual_scale;
00270 if (hmap)
00271 vbuf_ = view.memory_chunk();
00272 else
00273 {
00274 vil_image_resource_sptr ir =
00275 vil_new_image_resource_of_view(view);
00276 this->create_buffer(rmp, zx_, zy_, ir);
00277 valid_buffer_ = true;
00278 }
00279 }
00280 else if (hmap){
00281 view = the_image_->get_view(i0,ni,j0,nj);
00282 sni_ = view.ni(); snj_ = view.nj();
00283 vbuf_= view.memory_chunk();
00284 } else
00285 this->create_buffer(rmp, i0, j0, ni, nj, zx_, zy_);}
00286
00287 if (valid_buffer_&&!hmap)
00288 {
00289 buffer_->draw_viewport_as_image();
00290 return true;
00291 }
00292 else
00293 if (vbuf_&&vgui_view_render(vbuf_->data(),
00294 sni_, snj_,
00295 zx_, zy_,
00296 GL_RGB, GL_UNSIGNED_BYTE, hmap,
00297 0, &fRmap, &fGmap, &fBmap))
00298 {
00299 #ifdef RENDER_TIMER
00300 vcl_cout << "Directly Byte RGB Rendered in "
00301 << t.real() << "msecs\n";
00302 #endif
00303 valid_buffer_ = false;
00304 buffer_params_ = rmp;
00305 return true;
00306 }
00307 return false;
00308 }
00309
00310 #if 0 // Case 4 is currently disabled in anticipation of handling
00311
00312
00313 case 4:
00314 {
00315 vbl_array_1d<float> fRmap = rm.fRmap();
00316 vbl_array_1d<float> fGmap = rm.fGmap();
00317 vbl_array_1d<float> fBmap = rm.fBmap();
00318 vbl_array_1d<float> fAmap = rm.fAmap();
00319 if (!(fRmap.size()&&fGmap.size()&&fBmap.size()&&fAmap.size()))
00320 return false;
00321 if (valid_buffer_&&!hmap)
00322 {
00323 buffer_->draw_viewport_as_image();
00324 buffer_params_ = rmp;
00325 }
00326 else
00327 if (vbuf_&&vgui_view_render(reinterpret_cast<unsigned char*>(vbuf_->data()),
00328 sni_, snj_,
00329 zx_, zy_,
00330 GL_RGBA, GL_UNSIGNED_BYTE, hmap,
00331 0, &fRmap, &fGmap, &fBmap, &fAmap))
00332 {
00333 #ifdef RENDER_TIMER
00334 vcl_cout << "Directly Byte RGBA Rendered in "
00335 << t.real() << "msecs\n";
00336 #endif
00337 valid_buffer_ = false;
00338 buffer_params_ = rmp;
00339 return true;
00340 }
00341 return false;
00342 }
00343 #endif
00344 default:
00345 return false;
00346 }
00347 }
00348
00349 case VIL_PIXEL_FORMAT_UINT_16:
00350 {
00351 vgui_range_map<unsigned short> rm(*rmp);
00352 switch ( the_image_->nplanes() )
00353 {
00354 case 1:
00355 {
00356 vbl_array_1d<float> fLmap = rm.fLmap();
00357 if (!fLmap.size())
00358 return false;
00359 if (vp_changed||(hmap&&!vbuf_)||(!hmap&&!valid_buffer_)){
00360 vil_image_view<unsigned short> view;
00361 if (pyr)
00362 {
00363 view = pyr->get_copy_view(i0, ni, j0, nj, zoomx, actual_scale);
00364 if (!view) return false;
00365 sni_ = view.ni(); snj_ = view.nj();
00366 zx_/=actual_scale; zy_/=actual_scale;
00367 if (hmap)
00368 vbuf_ = view.memory_chunk();
00369 else
00370 {
00371 vil_image_resource_sptr ir =
00372 vil_new_image_resource_of_view(view);
00373 this->create_buffer(rmp, zx_, zy_, ir);
00374 valid_buffer_ = true;
00375 }
00376 }
00377 else if (hmap) {
00378 view = the_image_->get_view(i0,ni,j0,nj);
00379 sni_ = view.ni(); snj_ = view.nj();
00380 vbuf_= view.memory_chunk();
00381 } else
00382 this->create_buffer(rmp, i0, j0, ni, nj, zx_, zy_);}
00383
00384 if (valid_buffer_&&!hmap)
00385 {
00386 buffer_->draw_viewport_as_image();
00387 return true;
00388 }
00389 else
00390 if ( vbuf_&&vgui_view_render(vbuf_->data(),
00391 sni_, snj_,
00392 zx_, zy_,
00393 GL_LUMINANCE, GL_UNSIGNED_SHORT,
00394 hmap, &fLmap))
00395 {
00396 #ifdef RENDER_TIMER
00397 vcl_cout << "ushort Luminance Map Hardware Rendered in "
00398 << t.real() << "msecs\n";
00399 #endif
00400 valid_buffer_ = false;
00401 buffer_params_ = rmp;
00402 return true;
00403 }
00404 return false;
00405 }
00406
00407
00408
00409
00410 case 4:
00411 {
00412 if (hmap)
00413 return false;
00414 if (vp_changed||!valid_buffer_){
00415 vil_image_view<vil_rgba<unsigned short> > view;
00416 if (pyr) {
00417 view = pyr->get_copy_view(i0, ni, j0, nj, zoomx, actual_scale);
00418 sni_ = view.ni(); snj_ = view.nj();
00419 zx_/=actual_scale; zy_/=actual_scale;
00420 vil_image_resource_sptr ir =
00421 vil_new_image_resource_of_view(view);
00422 this->create_buffer(rmp, zx_, zy_, ir);
00423 valid_buffer_ = true;
00424 }else
00425 this->create_buffer(rmp, i0, j0, ni, nj, zx_, zy_);}
00426 if (valid_buffer_&&!hmap)
00427 {
00428 buffer_->draw_viewport_as_image();
00429 return true;
00430 }
00431 return false;
00432 }
00433 default:
00434 return false;
00435 }
00436 return false;
00437 }
00438 default:
00439 return false;
00440 }
00441 return false;
00442 }
00443
00444 void vgui_vil_image_renderer::
00445 render(vgui_range_map_params_sptr const& rmp)
00446 {
00447 if ( !the_image_ )
00448 return;
00449
00450
00451
00452 if (rmp&&rmp->use_glPixelMap_&&this->render_directly(rmp))
00453 return;
00454
00455
00456
00457
00458
00459
00460 if (!this->old_range_map_params(rmp)||!valid_buffer_)
00461 this->create_buffer(rmp);
00462
00463 this->draw_pixels();
00464 }
00465
00466
00467
00468 bool vgui_vil_image_renderer::
00469 old_range_map_params(vgui_range_map_params_sptr const& rmp)
00470 {
00471
00472
00473
00474 if (!buffer_params_&&!rmp)
00475 return true;
00476
00477
00478 if (!buffer_params_&&rmp)
00479 return false;
00480
00481
00482 if (buffer_params_&&!rmp)
00483 return false;
00484
00485
00486
00487 if (buffer_params_&&rmp)
00488 return *buffer_params_==*rmp;
00489
00490 return false;
00491 }