00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "vgui_section_buffer.h"
00027
00028 #include <vcl_cassert.h>
00029 #include <vcl_iostream.h>
00030 #include <vbl/vbl_array_1d.h>
00031 #include <vil1/vil1_image.h>
00032 #include <vil1/vil1_pixel.h>
00033
00034 #include <vil/vil_image_view.h>
00035 #include <vil/vil_image_resource.h>
00036 #include <vil/vil_pixel_format.h>
00037 #include "vgui_macro.h"
00038 #include "vgui_pixel.h"
00039 #include "vgui_section_render.h"
00040 #include "vgui_range_map_params.h"
00041 #include "vgui_range_map.h"
00042 #include "internals/vgui_gl_selection_macros.h"
00043 #include "internals/vgui_accelerate.h"
00044
00045 static bool debug = false;
00046
00047 namespace
00048 {
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 template <class InT, class OutT>
00060 bool
00061 convert_buffer( vil_image_view<InT> const& in,
00062 vgui_range_map_params_sptr const& rmp,
00063 OutT* out, vcl_ptrdiff_t hstep )
00064 {
00065 bool params_but_not_mappable = false;
00066 if (rmp&&rmp->n_components_==in.nplanes())
00067 {
00068 vgui_range_map<InT> rm(*rmp);
00069 if (rm.table_mapable())
00070 {
00071
00072 int O = rm.offset();
00073 switch ( in.nplanes() )
00074 {
00075 case 1:
00076 {
00077 vbl_array_1d<vxl_byte> Lmap = rm.Lmap();
00078 for ( unsigned j=0; j < in.nj(); ++j )
00079 for ( unsigned i=0; i < in.ni(); ++i )
00080 vgui_pixel_convert( Lmap[(unsigned)(in(i,j)+O)],
00081 *(out+i+j*hstep) );
00082 return true;
00083 }
00084 case 3:
00085 {
00086 vbl_array_1d<vxl_byte> Rmap = rm.Rmap();
00087 vbl_array_1d<vxl_byte> Gmap = rm.Gmap();
00088 vbl_array_1d<vxl_byte> Bmap = rm.Bmap();
00089 for ( unsigned j=0; j < in.nj(); ++j )
00090 for ( unsigned i=0; i < in.ni(); ++i )
00091 vgui_pixel_convert( Rmap[(unsigned)(in(i,j,0)+O)],
00092 Gmap[(unsigned)(in(i,j,1)+O)],
00093 Bmap[(unsigned)(in(i,j,2)+O)],
00094 *(out+i+j*hstep) );
00095 return true;
00096 }
00097 case 4:
00098 {
00099 vbl_array_1d<vxl_byte> Rmap = rm.Rmap();
00100 vbl_array_1d<vxl_byte> Gmap = rm.Gmap();
00101 vbl_array_1d<vxl_byte> Bmap = rm.Bmap();
00102 vbl_array_1d<vxl_byte> Xmap = rm.Xmap();
00103 if (rm.band_map_==vgui_range_map_params::RGBA_m)
00104 {
00105 for ( unsigned j=0; j < in.nj(); ++j )
00106 for ( unsigned i=0; i < in.ni(); ++i )
00107 vgui_pixel_convert( Rmap[(unsigned)(in(i,j,0)+O)],
00108 Gmap[(unsigned)(in(i,j,1)+O)],
00109 Bmap[(unsigned)(in(i,j,2)+O)],
00110 Xmap[(unsigned)(in(i,j,3)+O)],
00111 *(out+i+j*hstep) );
00112 return true;
00113 }
00114 else
00115 switch (rm.band_map_)
00116 {
00117 case vgui_range_map_params::RGB_m :
00118 for ( unsigned j=0; j < in.nj(); ++j )
00119 for ( unsigned i=0; i < in.ni(); ++i )
00120 vgui_pixel_convert( Rmap[(unsigned)(in(i,j,0))+O],
00121 Gmap[(unsigned)(in(i,j,1))+O],
00122 Bmap[(unsigned)(in(i,j,2))+O],
00123 Xmap[(unsigned)(rmp->max_X_)],
00124 *(out+i+j*hstep) );
00125 return true;
00126 case vgui_range_map_params::XRG_m :
00127 for ( unsigned j=0; j < in.nj(); ++j )
00128 for ( unsigned i=0; i < in.ni(); ++i )
00129 vgui_pixel_convert( Rmap[(unsigned)(in(i,j,3))+O],
00130 Gmap[(unsigned)(in(i,j,0))+O],
00131 Bmap[(unsigned)(in(i,j,1))+O],
00132 Xmap[(unsigned)(rmp->max_X_)],
00133 *(out+i+j*hstep) );
00134 return true;
00135 case vgui_range_map_params::RXB_m :
00136 for ( unsigned j=0; j < in.nj(); ++j )
00137 for ( unsigned i=0; i < in.ni(); ++i )
00138 vgui_pixel_convert( Rmap[(unsigned)(in(i,j,1))+O],
00139 Gmap[(unsigned)(in(i,j,3))+O],
00140 Bmap[(unsigned)(in(i,j,2))+O],
00141 Xmap[(unsigned)(rmp->max_X_)],
00142 *(out+i+j*hstep) );
00143 return true;
00144 case vgui_range_map_params::RGX_m :
00145 for ( unsigned j=0; j < in.nj(); ++j )
00146 for ( unsigned i=0; i < in.ni(); ++i )
00147 vgui_pixel_convert( Rmap[(unsigned)(in(i,j,0))+O],
00148 Gmap[(unsigned)(in(i,j,1))+O],
00149 Bmap[(unsigned)(in(i,j,3))+O],
00150 Xmap[(unsigned)(rmp->max_X_)],
00151 *(out+i+j*hstep) );
00152 return true;
00153 default:
00154 assert(!"invalid band_map");
00155 return false;
00156 }
00157 }
00158 default:
00159 assert(!"invalid nplanes");
00160 return false;
00161 }
00162 }
00163 if (rm.mapable())
00164 {
00165 switch ( in.nplanes() )
00166 {
00167 case 1:
00168 for ( unsigned j=0; j < in.nj(); ++j )
00169 for ( unsigned i=0; i < in.ni(); ++i )
00170 vgui_pixel_convert( rm.map_L_pixel(in(i,j)),
00171 *(out+i+j*hstep) );
00172 return true;
00173 case 3:
00174 for ( unsigned j=0; j < in.nj(); ++j )
00175 for ( unsigned i=0; i < in.ni(); ++i )
00176 vgui_pixel_convert( rm.map_R_pixel(in(i,j,0)),
00177 rm.map_G_pixel(in(i,j,1)),
00178 rm.map_B_pixel(in(i,j,2)),
00179 *(out+i+j*hstep) );
00180 return true;
00181 case 4:
00182 if (rm.band_map_==vgui_range_map_params::RGBA_m)
00183 {
00184 for ( unsigned j=0; j < in.nj(); ++j )
00185 for ( unsigned i=0; i < in.ni(); ++i )
00186 vgui_pixel_convert( rm.map_R_pixel(in(i,j,0)),
00187 rm.map_G_pixel(in(i,j,1)),
00188 rm.map_B_pixel(in(i,j,2)),
00189 rm.map_X_pixel(in(i,j,3)),
00190 *(out+i+j*hstep) );
00191 return true;
00192 }
00193 else
00194 {
00195 switch (rm.band_map_)
00196 {
00197 case vgui_range_map_params::RGB_m :
00198 for ( unsigned j=0; j < in.nj(); ++j )
00199 for ( unsigned i=0; i < in.ni(); ++i )
00200 vgui_pixel_convert( rm.map_R_pixel(in(i,j,0)),
00201 rm.map_G_pixel(in(i,j,1)),
00202 rm.map_B_pixel(in(i,j,2)),
00203 rm.map_X_pixel(0),
00204 *(out+i+j*hstep) );
00205 break;
00206 case vgui_range_map_params::XRG_m :
00207 for ( unsigned j=0; j < in.nj(); ++j )
00208 for ( unsigned i=0; i < in.ni(); ++i )
00209 vgui_pixel_convert( rm.map_R_pixel(in(i,j,3)),
00210 rm.map_G_pixel(in(i,j,1)),
00211 rm.map_B_pixel(in(i,j,2)),
00212 rm.map_X_pixel(0),
00213 *(out+i+j*hstep) );
00214 break;
00215 case vgui_range_map_params::RXB_m :
00216 for ( unsigned j=0; j < in.nj(); ++j )
00217 for ( unsigned i=0; i < in.ni(); ++i )
00218 vgui_pixel_convert( rm.map_R_pixel(in(i,j,1)),
00219 rm.map_G_pixel(in(i,j,3)),
00220 rm.map_B_pixel(in(i,j,2)),
00221 rm.map_X_pixel(0),
00222 *(out+i+j*hstep) );
00223 break;
00224 case vgui_range_map_params::RGX_m :
00225 for ( unsigned j=0; j < in.nj(); ++j )
00226 for ( unsigned i=0; i < in.ni(); ++i )
00227 vgui_pixel_convert( rm.map_R_pixel(in(i,j,0)),
00228 rm.map_G_pixel(in(i,j,1)),
00229 rm.map_B_pixel(in(i,j,3)),
00230 rm.map_X_pixel(0),
00231 *(out+i+j*hstep) );
00232 break;
00233 default:
00234 assert(!"invalid band_map");
00235 return false;
00236 }
00237 }
00238 default:
00239 assert(!"invalid nplanes");
00240 return false;
00241 }
00242 }
00243 params_but_not_mappable = true;
00244 }
00245
00246
00247 if (params_but_not_mappable || !rmp || rmp->n_components_!=in.nplanes())
00248 {
00249 switch ( in.nplanes() )
00250 {
00251 case 1:
00252 for ( unsigned j=0; j < in.nj(); ++j )
00253 for ( unsigned i=0; i < in.ni(); ++i )
00254 vgui_pixel_convert( in(i,j), *(out+i+j*hstep) );
00255 return true;
00256 case 3:
00257 for ( unsigned j=0; j < in.nj(); ++j )
00258 for ( unsigned i=0; i < in.ni(); ++i )
00259 vgui_pixel_convert( in(i,j,0), in(i,j,1), in(i,j,2),
00260 *(out+i+j*hstep) );
00261 return true;
00262 case 4:
00263 for ( unsigned j=0; j < in.nj(); ++j )
00264 for ( unsigned i=0; i < in.ni(); ++i )
00265 vgui_pixel_convert( in(i,j,0), in(i,j,1), in(i,j,2),
00266 in(i,j,3), *(out+i+j*hstep) );
00267 return true;
00268 default:
00269 assert(!"invalid nplanes");
00270 return false;
00271 }
00272 }
00273 else
00274 return false;
00275 }
00276
00277
00278
00279
00280
00281
00282 template <class InT>
00283 bool
00284 convert_image( vil_image_view<InT> const& in,
00285 vgui_range_map_params_sptr const& rmp,
00286 void* out, vcl_ptrdiff_t hstep,
00287 GLenum format, GLenum type )
00288 {
00289 bool result = false;
00290
00291 #define Code(BufferType) result=convert_buffer(in,rmp,(BufferType*)out,hstep);
00292 ConditionListBegin;
00293 ConditionListBody( format, type );
00294 ConditionListFail {
00295
00296
00297 assert( false );
00298 }
00299 #undef Code
00300
00301 return result;
00302 }
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 vgui_section_buffer::
00315 vgui_section_buffer( unsigned in_x, unsigned in_y,
00316 unsigned in_w, unsigned in_h,
00317 GLenum in_format,
00318 GLenum in_type )
00319 : format_( in_format ),
00320 type_( in_type ),
00321 x_( in_x ),
00322 y_( in_y ),
00323 w_( in_w ),
00324 h_( in_h ),
00325 zoomx_(1.0f),
00326 zoomy_(1.0f),
00327 allocw_( w_ ),
00328 alloch_( h_ ),
00329 buffer_( 0 ),
00330 buffer_ok_( false )
00331 {
00332 assert( w_ > 0 && h_ > 0 );
00333
00334
00335
00336 if ( format_ == GL_NONE && type_ == GL_NONE )
00337 vgui_accelerate::instance()->vgui_choose_cache_format( &format_, &type_ );
00338 else if ( format_ == GL_NONE || type_ == GL_NONE )
00339 assert(false);
00340
00341
00342 assert( allocw_*alloch_ >= w_*h_ );
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 #define Code(BufferType) buffer_=new BufferType[allocw_*alloch_];
00354 ConditionListBegin;
00355 ConditionListBody( format_, type_ );
00356 ConditionListFail {
00357 vcl_cerr << __FILE__ << ": " << __LINE__ << ": unknown GL format ("
00358 << format_ << ") and type (" << type_ << ").\n"
00359 << "You can probably easily add support here.\n";
00360 assert( false );
00361 }
00362 #undef Code
00363 }
00364
00365
00366
00367
00368
00369 vgui_section_buffer::
00370 ~vgui_section_buffer()
00371 {
00372
00373
00374
00375
00376
00377 #define Code(BufferType) delete[] static_cast<BufferType*>(buffer_);
00378 ConditionListBegin;
00379 ConditionListBody( format_, type_ );
00380 ConditionListFail {
00381 assert( false );
00382 }
00383 #undef Code
00384 }
00385
00386
00387
00388
00389
00390 void
00391 vgui_section_buffer::
00392 apply( vil_image_resource_sptr const& image_in,
00393 vgui_range_map_params_sptr const& rmp)
00394 {
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 #define DoCase( T ) \
00405 case T: \
00406 { \
00407 typedef vil_pixel_format_type_of<T>::type Type; \
00408 vil_image_view<Type> img = image_in->get_view( x_, w_, y_, h_ ); \
00409 assert( img ); \
00410 conversion_okay = convert_image(img,rmp,buffer_,allocw_,format_,type_); \
00411 break; \
00412 }
00413
00414 bool conversion_okay = false;
00415 vil_pixel_format component_format =
00416 vil_pixel_format_component_format( image_in->pixel_format() );
00417
00418 switch ( component_format )
00419 {
00420 DoCase( VIL_PIXEL_FORMAT_UINT_32 )
00421 DoCase( VIL_PIXEL_FORMAT_INT_32 )
00422 DoCase( VIL_PIXEL_FORMAT_UINT_16 )
00423 DoCase( VIL_PIXEL_FORMAT_INT_16 )
00424 DoCase( VIL_PIXEL_FORMAT_BYTE )
00425 DoCase( VIL_PIXEL_FORMAT_SBYTE )
00426 DoCase( VIL_PIXEL_FORMAT_FLOAT )
00427 DoCase( VIL_PIXEL_FORMAT_DOUBLE )
00428 DoCase( VIL_PIXEL_FORMAT_BOOL )
00429 default:
00430 vcl_cerr << __FILE__ << ": " << __LINE__
00431 << ": can't handle image pixel format "
00432 << component_format << '\n';
00433 }
00434
00435 #undef DoCase
00436
00437 if ( !conversion_okay ) {
00438 vcl_cerr << __FILE__ << ": " << __LINE__ << ": conversion failed\n";
00439 }
00440
00441 buffer_ok_ = conversion_okay;
00442 }
00443
00444
00445
00446
00447
00448 void
00449 vgui_section_buffer::
00450 apply( vil1_image const& image,
00451 vgui_range_map_params_sptr const& rmp)
00452 {
00453
00454
00455 assert( image.planes() == 1 );
00456 vil1_pixel_format_t pixel_format = vil1_pixel_format( image );
00457
00458 bool conversion_ok = false;
00459 bool section_ok = false;
00460
00461 #define DoCase( PixelFormat, DataType, NComp ) \
00462 case PixelFormat: \
00463 { \
00464 DataType* temp_buffer = new DataType[ w_ * h_ * NComp ]; \
00465 section_ok = image.get_section( temp_buffer, x_, y_, w_, h_ ); \
00466 if ( section_ok ) { \
00467 vil_image_view<DataType> view( temp_buffer, w_, h_, NComp, \
00468 NComp, NComp*w_, 1 ); \
00469 conversion_ok = convert_image(view,rmp,buffer_,allocw_,format_,type_);\
00470 } \
00471 delete[] temp_buffer; \
00472 break; \
00473 }
00474
00475 switch ( pixel_format )
00476 {
00477 DoCase( VIL1_BYTE, vxl_byte, 1 )
00478 DoCase( VIL1_UINT16, vxl_uint_16, 1 )
00479 DoCase( VIL1_UINT32, vxl_uint_32, 1 )
00480 DoCase( VIL1_FLOAT, float, 1 )
00481 DoCase( VIL1_DOUBLE, double, 1 )
00482 DoCase( VIL1_RGB_BYTE, vxl_byte, 3 )
00483 DoCase( VIL1_RGB_UINT16, vxl_uint_16, 3 )
00484 DoCase( VIL1_RGB_FLOAT, float, 3 )
00485 DoCase( VIL1_RGB_DOUBLE, double, 3 )
00486 DoCase( VIL1_RGBA_BYTE, vxl_byte, 4 )
00487 default:
00488 vcl_cerr << __FILE__ << ": " << __LINE__
00489 << ": can't handle image pixel format "
00490 << vil1_print( pixel_format ) << '\n';
00491 }
00492
00493 #undef DoCase
00494
00495 if ( !conversion_ok ) {
00496 vcl_cerr << __FILE__ << ": " << __LINE__ << ": conversion failed\n";
00497 }
00498
00499 if (debug || !section_ok)
00500 vcl_cerr << (section_ok ? "section ok" : "section bad") << vcl_endl;
00501
00502 buffer_ok_ = section_ok && conversion_ok;
00503 }
00504
00505
00506
00507
00508 bool
00509 vgui_section_buffer::
00510 draw_as_rectangle( float x0, float y0, float x1, float y1 ) const
00511 {
00512 glColor3i( 0, 1, 0 );
00513 glLineWidth( 1 );
00514 glBegin( GL_LINE_LOOP );
00515 glVertex2f( x0, y0 );
00516 glVertex2f( x1, y0 );
00517 glVertex2f( x1, y1 );
00518 glVertex2f( x0, y1 );
00519 glEnd();
00520 return true;
00521 }
00522
00523
00524 bool
00525 vgui_section_buffer::
00526 draw_as_rectangle() const
00527 {
00528 return draw_as_rectangle( (float)x_, (float)y_, float(x_+w_), float(y_+h_) );
00529 }
00530
00531
00532
00533
00534
00535 bool
00536 vgui_section_buffer::
00537 draw_as_image( float x0, float y0, float x1, float y1 ) const
00538 {
00539 if ( !buffer_ok_ ) {
00540 vgui_macro_warning << "bad buffer in draw_as_image()\n";
00541 return draw_as_rectangle( x0, y0, x1, y1 );
00542 }
00543
00544 return vgui_section_render( buffer_,
00545 allocw_, alloch_,
00546 x0,y0, x1, y1,
00547 format_, type_ ,0 );
00548 }
00549
00550 bool
00551 vgui_section_buffer::
00552 draw_as_image() const
00553 {
00554 return draw_as_image( (float)x_, (float)y_, float(x_+w_), float(y_+h_) );
00555 }
00556
00557 bool
00558 vgui_section_buffer::draw_viewport_as_image() const
00559 {
00560
00561 return vgui_view_render( buffer_,
00562 w_, h_,
00563 zoomx_, zoomy_,
00564 format_, type_ ,false);
00565 }