core/vil/file_formats/vil_openjpeg.cxx
Go to the documentation of this file.
00001 //==========
00002 // Kitware (c) 2010
00003 //
00004 // Restrictions applicable to use by the US Government:
00005 //
00006 // UNLIMITED RIGHTS
00007 //
00008 // Restrictions applicable for all other users:
00009 //
00010 // This software and all information and expression are the property of Kitware, Inc. All Rights Reserved.
00011 //==========
00012 //:
00013 // \file
00014 // \brief Image I/O for JPEG2000 imagery using OpenJPEG
00015 // \author Chuck Atkins
00016 
00017 #include <vcl_cmath.h>
00018 #include <vcl_cstring.h> // for std::memcmp()
00019 #include <vcl_iostream.h>
00020 #include <vcl_stdexcept.h>
00021 #include <vcl_limits.h>
00022 
00023 #include <vil/vil_stream.h>
00024 #include <vbl/vbl_smart_ptr.h>
00025 #include <vbl/vbl_smart_ptr.txx>
00026 #include <vil/vil_image_view.txx>
00027 
00028 // TODO: How can we avoid using the "deprecated" functions?
00029 #define USE_OPJ_DEPRECATED
00030 extern "C" {
00031   #include <openjpeg.h>
00032 }
00033 
00034 #include "vil_openjpeg.h"
00035 
00036 
00037 typedef vbl_smart_ptr<vil_stream> vil_stream_sptr;
00038 
00039 //------------------------------------------------------------------------------
00040 // Taken from
00041 //------------------------------------------------------------------------------
00042 // class vil_openjpeg_file_format
00043 //
00044 
00045 vil_image_resource_sptr
00046 vil_openjpeg_file_format
00047 ::make_input_image(vil_stream* vs, vil_openjpeg_format opjfmt)
00048 {
00049   vil_openjpeg_image *im = new vil_openjpeg_image(vs, opjfmt);
00050 
00051   if ( !im->is_valid() )
00052   {
00053     delete im;
00054     return 0;
00055   }
00056   return im;
00057 }
00058 
00059 
00060 vil_image_resource_sptr
00061 vil_openjpeg_file_format
00062 ::make_output_image(vil_stream* vs,
00063                     unsigned int ni, unsigned int nj, unsigned int nplanes,
00064                     vil_pixel_format format, vil_openjpeg_format opjfmt)
00065 {
00066   return 0;
00067 }
00068 
00069 
00070 //------------------------------------------------------------------------------
00071 // Various OpenJPEG parameters and data structures
00072 //
00073 struct opj_header
00074 {
00075   vxl_uint_32 tile_width_;
00076   vxl_uint_32 tile_height_;
00077   vxl_uint_32 num_tiles_x_;
00078   vxl_uint_32 num_tiles_y_;
00079   vxl_int_32  x0_;
00080   vxl_int_32  y0_;
00081   vxl_uint_32 num_reductions_;
00082 };
00083 
00084 
00085 //------------------------------------------------------------------------------
00086 // OpenJPEG decoder helper class
00087 //
00088 class vil_openjpeg_decoder
00089 {
00090  public:
00091   vil_openjpeg_decoder(OPJ_CODEC_FORMAT opj_codec_format);
00092   ~vil_openjpeg_decoder(void);
00093 
00094   bool error(void) const;
00095   void silence(void);
00096 
00097   bool init_from_stream(unsigned int reduction, void *stream);
00098   bool set_decode_area(unsigned int x, unsigned int y,
00099                        unsigned int w, unsigned int h);
00100   opj_image_t * take_image(void);
00101   opj_image_t * decode(void);
00102 
00103   const opj_header * header(void) const;
00104 
00105  private:
00106   opj_dparameters_t params_;
00107   opj_codec_t *codec_;
00108   opj_image_t *image_;
00109   opj_stream_t *stream_;
00110   opj_header header_;
00111   OPJ_CODEC_FORMAT opj_codec_format_;
00112 
00113   bool error_;
00114   bool silent_;
00115 
00116   bool init_decoder(unsigned int reduction);
00117   bool init_stream(void *stream);
00118   bool read_header(void);
00119 
00120   // OpenJPEG I/O helper functions
00121   static vxl_uint_32 opj_vil_stream_read(void *p_buffer,
00122                                          vxl_uint_32 p_nb_bytes,
00123                                          void *p_user_data);
00124   static vxl_uint_32 opj_vil_stream_write(void *p_buffer,
00125                                           vxl_uint_32 p_nb_bytes,
00126                                           void *p_user_data);
00127   static vxl_uint_32 opj_vil_stream_skip(vxl_uint_32 p_nb_bytes,
00128                                          void *p_user_data);
00129   static bool opj_vil_stream_seek(vxl_uint_32 p_nb_bytes,
00130                                   void *p_user_data);
00131 
00132   // OpenJPEG logging functions
00133   static void opj_event_info(const char *msg, void *data);
00134   static void opj_event_warning(const char *msg, void *data);
00135   static void opj_event_error(const char *msg, void *data);
00136 };
00137 
00138 
00139 //------------------------------------------------------------------------------
00140 // OpenJPEG image internal implementation
00141 //
00142 struct vil_openjpeg_image_impl
00143 {
00144   // OpenJPEG data structures
00145   opj_cparameters_t encode_params_;
00146   opj_codec_t *encode_codec_;
00147   opj_image_t *image_;
00148   opj_header header_;
00149   OPJ_CODEC_FORMAT opj_codec_format_;
00150 
00151   // Fields needed for the vil implementation
00152   vil_stream_sptr vstream_;
00153   vil_streampos vstream_start_;
00154   bool is_valid_;
00155   bool error_;
00156 
00157   vil_openjpeg_image_impl(void)
00158   : encode_codec_(0), image_(0), vstream_(0), vstream_start_(0),
00159     is_valid_(false), error_(false)
00160   {
00161     vcl_memset(&this->encode_params_, 0, sizeof(opj_cparameters_t));
00162     vcl_memset(&this->header_, 0, sizeof(opj_header));
00163   }
00164 };
00165 
00166 
00167 //------------------------------------------------------------------------------
00168 // class vil_openjpeg_decoder
00169 //
00170 
00171 
00172 vil_openjpeg_decoder
00173 ::vil_openjpeg_decoder(OPJ_CODEC_FORMAT opj_codec_format)
00174 : codec_(0), image_(0), stream_(0), opj_codec_format_(opj_codec_format),
00175   error_(false), silent_(false)
00176 {
00177   vcl_memset(&this->params_, 0, sizeof(opj_dparameters_t));
00178   vcl_memset(&this->header_, 0, sizeof(opj_header));
00179 }
00180 
00181 
00182 vil_openjpeg_decoder
00183 ::~vil_openjpeg_decoder(void)
00184 {
00185   // De-allocate any necessary OpenJPEG data structures
00186   if ( this->stream_ )
00187   {
00188     opj_stream_destroy(this->stream_);
00189     this->stream_ = 0;
00190   }
00191   if ( this->codec_ )
00192   {
00193     opj_destroy_codec(this->codec_);
00194     this->codec_ = 0;
00195   }
00196   if ( this->image_ )
00197   {
00198     opj_image_destroy(this->image_);
00199     this->image_ = 0;
00200   }
00201 }
00202 
00203 
00204 bool
00205 vil_openjpeg_decoder
00206 ::error(void) const
00207 {
00208   return this->error_;
00209 }
00210 
00211 
00212 void
00213 vil_openjpeg_decoder
00214 ::silence(void)
00215 {
00216   this->silent_ = true;
00217 }
00218 
00219 
00220 bool
00221 vil_openjpeg_decoder
00222 ::init_from_stream(unsigned int reduction, void *stream)
00223 {
00224   if ( !init_stream(stream) )
00225     return false;
00226 
00227   if ( !init_decoder(reduction) )
00228     return false;
00229 
00230   if ( !read_header() )
00231     return false;
00232 
00233   return true;
00234 }
00235 
00236 
00237 bool
00238 vil_openjpeg_decoder
00239 ::init_stream(void *stream)
00240 {
00241   if ( this->stream_ )
00242   {
00243     opj_stream_destroy(this->stream_);
00244     this->stream_ = 0;
00245   }
00246 
00247   // Setup the input stream
00248   this->stream_ = opj_stream_default_create(true);
00249   if ( !this->stream_ )
00250     return false;
00251 
00252   // Configure the I/O methods for the opj stream using vil operations
00253   opj_stream_set_user_data(this->stream_, stream);
00254   opj_stream_set_read_function(this->stream_,
00255                                vil_openjpeg_decoder::opj_vil_stream_read);
00256   opj_stream_set_write_function(this->stream_,
00257                                 vil_openjpeg_decoder::opj_vil_stream_write);
00258   opj_stream_set_skip_function(this->stream_,
00259                                vil_openjpeg_decoder::opj_vil_stream_skip);
00260   opj_stream_set_seek_function(this->stream_,
00261                                vil_openjpeg_decoder::opj_vil_stream_seek);
00262 
00263   return true;
00264 }
00265 
00266 
00267 bool
00268 vil_openjpeg_decoder
00269 ::init_decoder(unsigned int reduction)
00270 {
00271   if ( this->codec_ )
00272   {
00273     opj_destroy_codec(this->codec_);
00274     this->codec_ = 0;
00275   }
00276 
00277   // Set decoder parameters
00278   vcl_memset(&this->params_, 0, sizeof(opj_dparameters_t));
00279   opj_set_default_decoder_parameters(&this->params_);
00280   this->params_.cp_reduce = reduction;
00281   this->params_.cp_layer = 0;
00282 
00283   // Create the decoder
00284   this->codec_ = opj_create_decompress(this->opj_codec_format_);
00285   if ( !this->codec_ )
00286     return false;
00287 
00288   // Configure the OpenJPEG event manager
00289   opj_set_info_handler(this->codec_,
00290                        vil_openjpeg_decoder::opj_event_info, this);
00291   opj_set_warning_handler(this->codec_,
00292                           vil_openjpeg_decoder::opj_event_warning, this);
00293   opj_set_error_handler(this->codec_,
00294                         vil_openjpeg_decoder::opj_event_error, this);
00295 
00296   // Initialize the decoder
00297   if ( !opj_setup_decoder( this->codec_, &this->params_) )
00298     return false;
00299   if ( this->error_ )
00300     return false;
00301 
00302   return true;
00303 }
00304 
00305 
00306 bool
00307 vil_openjpeg_decoder
00308 ::read_header(void)
00309 {
00310   if ( this->image_ )
00311   {
00312     opj_image_destroy(this->image_);
00313     this->image_ = 0;
00314   }
00315 
00316   return opj_read_header( this->codec_,
00317                          &this->image_,
00318                          &this->header_.x0_,
00319                          &this->header_.y0_,
00320                          &this->header_.tile_width_,
00321                          &this->header_.tile_height_,
00322                          &this->header_.num_tiles_x_,
00323                          &this->header_.num_tiles_y_,
00324                           this->stream_) && !this->error_;
00325 }
00326 
00327 
00328 bool
00329 vil_openjpeg_decoder
00330 ::set_decode_area(unsigned int x, unsigned int y,
00331                   unsigned int w, unsigned int h)
00332 {
00333   this->error_ = false;
00334   return opj_set_decode_area( this->codec_, x, y, w, h ) && !this->error_;
00335 }
00336 
00337 
00338 opj_image_t *
00339 vil_openjpeg_decoder
00340 ::take_image(void)
00341 {
00342   opj_image_t *image = this->image_;
00343   this->image_ = 0;
00344   return image;
00345 }
00346 
00347 
00348 opj_image_t *
00349 vil_openjpeg_decoder
00350 ::decode(void)
00351 {
00352   this->error_ = false;
00353   return opj_decode(this->codec_, this->stream_);
00354 }
00355 
00356 
00357 const opj_header *
00358 vil_openjpeg_decoder
00359 ::header(void) const
00360 {
00361   return &this->header_;
00362 }
00363 
00364 
00365 //------------------------------------------------------------------------------
00366 // Helper functions to read from vil_stream objects
00367 //
00368 
00369 vxl_uint_32
00370 vil_openjpeg_decoder
00371 ::opj_vil_stream_read(void *p_buffer,
00372                       vxl_uint_32 p_nb_bytes,
00373                       void *p_user_data)
00374 {
00375   vil_stream *stream = reinterpret_cast<vil_stream*>(p_user_data);
00376   vil_streampos b = stream->read(p_buffer, p_nb_bytes);
00377   if ( b == 0 || !stream->ok() )
00378   {
00379     return static_cast<vxl_uint_32>(-1);
00380   }
00381   if ( b > static_cast<vil_streampos>(vcl_numeric_limits<vxl_uint_32>::max()) )
00382   {
00383     throw vcl_runtime_error("Stream position outof range");
00384   }
00385   return static_cast<vxl_uint_32>(b);
00386 }
00387 
00388 
00389 vxl_uint_32
00390 vil_openjpeg_decoder
00391 ::opj_vil_stream_write(void *p_buffer,
00392                        vxl_uint_32 p_nb_bytes,
00393                        void *p_user_data)
00394 {
00395   vil_stream *stream = reinterpret_cast<vil_stream*>(p_user_data);
00396   vil_streampos b = stream->write(p_buffer, p_nb_bytes);
00397   if ( b == 0 || !stream->ok() )
00398   {
00399     return static_cast<vxl_uint_32>(-1);
00400   }
00401   if ( b > static_cast<vil_streampos>(vcl_numeric_limits<vxl_uint_32>::max()) )
00402   {
00403     throw vcl_runtime_error("Stream position outof range");
00404   }
00405   return static_cast<vxl_uint_32>(b);
00406 }
00407 
00408 
00409 vxl_uint_32
00410 vil_openjpeg_decoder
00411 ::opj_vil_stream_skip(vxl_uint_32 p_nb_bytes,
00412                       void *p_user_data)
00413 {
00414   vil_stream *stream = reinterpret_cast<vil_stream*>(p_user_data);
00415   vil_streampos start = stream->tell();
00416   stream->seek(start+p_nb_bytes);
00417   if ( !stream->ok() )
00418   {
00419     return static_cast<vxl_uint_32>(-1);
00420   }
00421   vil_streampos end = stream->tell();
00422   vil_streampos b = end-start;
00423   if ( b > static_cast<vil_streampos>(vcl_numeric_limits<vxl_uint_32>::max()) )
00424   {
00425     throw vcl_runtime_error("Stream position outof range");
00426   }
00427   return static_cast<vxl_uint_32>(b);
00428 }
00429 
00430 
00431 bool
00432 vil_openjpeg_decoder
00433 ::opj_vil_stream_seek( vxl_uint_32 p_nb_bytes,
00434                        void *p_user_data)
00435 {
00436   vil_stream *stream = reinterpret_cast<vil_stream*>(p_user_data);
00437   stream->seek(p_nb_bytes);
00438   if ( !stream->ok() )
00439   {
00440     return false;
00441   }
00442   vil_streampos pos = stream->tell();
00443   if ( pos > static_cast<vil_streampos>(vcl_numeric_limits<vxl_uint_32>::max()) )
00444   {
00445     throw vcl_runtime_error("Stream position outof range");
00446   }
00447   return p_nb_bytes == static_cast<vxl_uint_32>(pos);
00448 }
00449 
00450 
00451 //------------------------------------------------------------------------------
00452 // Helper functions for OpenJPEG error handling
00453 //
00454 
00455 void
00456 vil_openjpeg_decoder
00457 ::opj_event_info(const char *msg, void *data)
00458 {
00459   vcl_clog << "vil_openjpeg_decoder::INFO  : " << msg << vcl_endl;
00460 }
00461 
00462 
00463 void
00464 vil_openjpeg_decoder
00465 ::opj_event_warning(const char *msg, void *data)
00466 {
00467   vcl_clog << "vil_openjpeg_decoder::WARN  : " << msg << vcl_endl;
00468 }
00469 
00470 
00471 void
00472 vil_openjpeg_decoder
00473 ::opj_event_error(const char *msg, void *data)
00474 {
00475   vil_openjpeg_decoder *decoder = reinterpret_cast<vil_openjpeg_decoder*>(data);
00476   if ( !decoder->silent_ )
00477     vcl_cerr << "vil_openjpeg_decoder::ERROR : " << msg << vcl_endl;
00478   decoder->error_ = true;
00479 }
00480 
00481 
00482 //------------------------------------------------------------------------------
00483 // class vil_openjpeg_image
00484 //
00485 
00486 vil_openjpeg_image
00487 ::vil_openjpeg_image (vil_stream* is,
00488                       unsigned int ni, unsigned int nj, unsigned int nplanes,
00489                       vil_pixel_format format, vil_openjpeg_format opjfmt)
00490 : impl_(new vil_openjpeg_image_impl)
00491 {
00492   // Write support is currently not implemented
00493 }
00494 
00495 
00496 vil_openjpeg_image
00497 ::vil_openjpeg_image(vil_stream* is, vil_openjpeg_format opjfmt)
00498 : impl_(new vil_openjpeg_image_impl)
00499 {
00500   switch ( opjfmt )
00501   {
00502     case VIL_OPENJPEG_JP2: this->impl_->opj_codec_format_ = CODEC_JP2; break;
00503     case VIL_OPENJPEG_JPT: this->impl_->opj_codec_format_ = CODEC_JPT; break;
00504     case VIL_OPENJPEG_J2K: this->impl_->opj_codec_format_ = CODEC_J2K; break;
00505     default: return;
00506   }
00507 
00508   this->impl_->vstream_ = is;
00509   this->impl_->vstream_start_ = is->tell();
00510 
00511   if ( !this->validate_format() )
00512     return;
00513 
00514   this->impl_->vstream_->seek(this->impl_->vstream_start_);
00515   vil_openjpeg_decoder decoder(this->impl_->opj_codec_format_);
00516   if ( !decoder.init_from_stream(0, this->impl_->vstream_.as_pointer()) )
00517     return;
00518 
00519   // Copy headers and image from decoder
00520   vcl_memcpy(&this->impl_->header_, decoder.header(), sizeof(opj_header));
00521   this->impl_->image_ = decoder.take_image();
00522 
00523   // Delay num reduction computation until requested
00524   this->impl_->header_.num_reductions_ = static_cast<vxl_uint_32>(-1);
00525 
00526 #if 0 // Move to a lazy evaluation
00527   // Find out how many reductions are available
00528   // There ought to be a better way to do this, but I haven't found one yet :-(
00529   decoder.silence();
00530   for (;;)
00531   {
00532     // This will fail when we ask for a reduction that doesn't exist
00533     this->impl_->vstream_->seek(this->impl_->vstream_start_);
00534     if ( !decoder.init_from_stream(this->impl_->header_.num_reductions_ + 1,
00535                                   this->impl_->vstream_.as_pointer()) )
00536       break;
00537     // If init_from_stream succeeded, that reduction is available
00538     ++this->impl_->header_.num_reductions_;
00539   }
00540 #endif // 0
00541 
00542   // No errors have occurred (except expected one) so mark success
00543   this->impl_->is_valid_ = true;
00544 }
00545 
00546 
00547 vil_openjpeg_image
00548 ::~vil_openjpeg_image(void)
00549 {
00550   // De-allocate any necessary OpenJPEG data structures
00551   if ( this->impl_->image_ )
00552   {
00553     opj_image_destroy(this->impl_->image_);
00554     this->impl_->image_ = 0;
00555   }
00556   delete this->impl_;
00557 }
00558 
00559 
00560 bool
00561 vil_openjpeg_image
00562 ::validate_format(void)
00563 {
00564   vil_streampos pos_start = this->impl_->vstream_->tell();
00565 
00566   switch ( this->impl_->opj_codec_format_ )
00567   {
00568   case CODEC_JP2 :
00569   {
00570     // See specification ISO/IEC 15444-1 Part 1
00571     unsigned char sig[12] =
00572       {0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A};
00573     unsigned char sig_file[12];
00574     this->impl_->vstream_->read(sig_file, 12);
00575     if ( vcl_memcmp( sig, sig_file, 12) == 0 )
00576     {
00577       this->impl_->vstream_->seek(pos_start);
00578       return true;
00579     }
00580     break;
00581   }
00582   case CODEC_JPT: break; // Although supported by OpenJPEG, the JPT codec
00583                          // (JPEG2000 JPIP) is not yet implemented by the
00584                          // vil implementation
00585   case CODEC_J2K:
00586   {
00587     // See specification ISO/IEC 15444-1 Part 1
00588     unsigned char sig[2] = {0xFF, 0x4F};
00589     unsigned char sig_file[2];
00590     this->impl_->vstream_->read(sig_file, 2);
00591     if ( vcl_memcmp( sig, sig_file, 2) == 0 )
00592     {
00593       this->impl_->vstream_->seek(pos_start);
00594       return true;
00595     }
00596     break;
00597   }
00598   default : break;
00599   }
00600 
00601   return false;
00602 }
00603 
00604 
00605 bool
00606 vil_openjpeg_image
00607 ::is_valid(void) const
00608 {
00609   return this->impl_->is_valid_;
00610 }
00611 
00612 
00613 unsigned int
00614 vil_openjpeg_image
00615 ::nreductions(void) const
00616 {
00617   if ( !this->impl_->is_valid_ )
00618     return static_cast<unsigned int>(-1);
00619   if ( this->impl_->header_.num_reductions_ == static_cast<vxl_uint_32>(-1) )
00620   {
00621     vil_openjpeg_decoder decoder(this->impl_->opj_codec_format_);
00622     // Find out how many reductions are available
00623     // There ought to be a better way to do this, but I haven't found one yet
00624     decoder.silence();
00625     unsigned int num_reductions = 0;
00626     for (;;)
00627     {
00628       // This will fail when we ask for a reduction that doesn't exist
00629       this->impl_->vstream_->seek(this->impl_->vstream_start_);
00630       if ( !decoder.init_from_stream(num_reductions + 1,
00631                                     this->impl_->vstream_.as_pointer()) )
00632         break;
00633       // If init_from_stream succeeded, that reduction is available
00634       ++num_reductions;
00635     }
00636     this->impl_->header_.num_reductions_ = num_reductions;
00637   }
00638   return this->impl_->header_.num_reductions_;
00639 }
00640 
00641 
00642 unsigned int
00643 vil_openjpeg_image
00644 ::nplanes() const
00645 {
00646   if ( !this->impl_->is_valid_ )
00647     return static_cast<unsigned int>(-1);
00648   return this->impl_->image_->numcomps;
00649 }
00650 
00651 
00652 unsigned int
00653 vil_openjpeg_image
00654 ::ni() const
00655 {
00656   if ( !this->impl_->is_valid_ )
00657     return static_cast<unsigned int>(-1);
00658   return this->impl_->image_->comps[0].w;
00659 }
00660 
00661 
00662 unsigned int
00663 vil_openjpeg_image
00664 ::nj() const
00665 {
00666   if ( !this->impl_->is_valid_ )
00667     return static_cast<unsigned int>(-1);
00668   return this->impl_->image_->comps[0].h;
00669 }
00670 
00671 
00672 int
00673 vil_openjpeg_image
00674 ::maxbpp(void) const
00675 {
00676   if ( !this->impl_->is_valid_ )
00677     return -1;
00678 
00679   int maxbpp = this->impl_->image_->comps[0].prec;
00680   for ( unsigned int i = 1; i < this->impl_->image_->numcomps; ++i )
00681   {
00682     if ( static_cast<unsigned int>(maxbpp) < this->impl_->image_->comps[i].prec )
00683       maxbpp = this->impl_->image_->comps[i].prec;
00684   }
00685   return maxbpp;
00686 }
00687 
00688 
00689 enum vil_pixel_format
00690 vil_openjpeg_image
00691 ::pixel_format() const
00692 {
00693   // NOTE:
00694   // 1.  Up to 32 bit pixels are supported
00695   // 2.  An assumption is also made by OpenJPEG that all components are integral
00696   // 3.  This current vil implementation will always generate unsigned
00697   //     components
00698   switch ( this->maxbpp() )
00699   {
00700     case 8  : return VIL_PIXEL_FORMAT_BYTE;
00701     case 16 : return VIL_PIXEL_FORMAT_UINT_16;
00702     case 32 : return VIL_PIXEL_FORMAT_UINT_32;
00703     default : return VIL_PIXEL_FORMAT_UNKNOWN;
00704   }
00705 }
00706 
00707 
00708 const char *
00709 vil_openjpeg_image
00710 ::file_format()
00711 {
00712   switch ( this->impl_->opj_codec_format_ )
00713   {
00714     case CODEC_JP2: return "jp2";
00715     case CODEC_JPT: return "jpt";
00716     case CODEC_J2K: return "j2k";
00717     default: return "openjpeg";
00718   }
00719 }
00720 
00721 
00722 vil_image_view_base_sptr
00723 vil_openjpeg_image
00724 ::get_copy_view(unsigned int i0, unsigned int ni,
00725                 unsigned int j0, unsigned int nj) const
00726 {
00727   return this->get_copy_view_reduced(i0, ni, j0, nj, 0);
00728 }
00729 
00730 
00731 vil_image_view_base_sptr
00732 vil_openjpeg_image
00733 ::get_copy_view_reduced(unsigned int i0, unsigned int ni,
00734                         unsigned int j0, unsigned int nj,
00735                         unsigned int reduction) const
00736 {
00737   if ( !this->impl_->is_valid_ )
00738     return 0;
00739 
00740   if ( reduction > this->impl_->header_.num_reductions_ )
00741     return 0;
00742 
00743   vil_pixel_format pixel_format = this->pixel_format();
00744   if ( pixel_format == VIL_PIXEL_FORMAT_UNKNOWN )
00745     return 0;
00746 
00747   // Set up decoder
00748   this->impl_->vstream_->seek(this->impl_->vstream_start_);
00749   vil_openjpeg_decoder decoder(this->impl_->opj_codec_format_);
00750   if ( !decoder.init_from_stream(reduction, this->impl_->vstream_.as_pointer()) )
00751     return 0;
00752 
00753   // Configure the ROI
00754   int adj_mask = ~( (1 << reduction) - 1);
00755   i0 &= adj_mask; j0 &= adj_mask;
00756   ni &= adj_mask; nj &= adj_mask;
00757   if ( !decoder.set_decode_area( i0, j0, i0 + ni, j0 + nj ) )
00758     return 0;
00759 
00760   // Decode the JPEG2000 data
00761   opj_image_t *opj_view = decoder.decode();
00762   if ( !opj_view || decoder.error() )
00763     return 0;
00764 
00765   // Adjust ROI for reduction
00766   i0 >>= reduction;
00767   j0 >>= reduction;
00768   ni >>= reduction;
00769   nj >>= reduction;
00770 
00771   // Copy pixels
00772   switch ( pixel_format )
00773   {
00774   case VIL_PIXEL_FORMAT_BYTE :
00775     return this->opj2vil<vxl_byte>(opj_view, i0, ni, j0, nj);
00776   case VIL_PIXEL_FORMAT_UINT_16 :
00777     return this->opj2vil<vxl_uint_16>(opj_view, i0, ni, j0, nj);
00778   case VIL_PIXEL_FORMAT_UINT_32 :
00779     return this->opj2vil<vxl_uint_32>(opj_view, i0, ni, j0, nj);
00780   default: return 0;
00781   }
00782 }
00783 
00784 
00785 template<typename T_PIXEL>
00786 vil_image_view_base_sptr
00787 vil_openjpeg_image
00788 ::opj2vil(
00789   void *opj_view,
00790   unsigned int i0, unsigned int ni, unsigned int j0, unsigned int nj) const
00791 {
00792   opj_image_t *opj_view_t = reinterpret_cast<opj_image_t*>(opj_view);
00793   unsigned int np = opj_view_t->numcomps;
00794 
00795   vil_memory_chunk_sptr chunk =
00796     new vil_memory_chunk(ni*nj*np*sizeof(T_PIXEL), this->pixel_format());
00797 
00798   vil_image_view<T_PIXEL> *vil_view_t = new vil_image_view<T_PIXEL>(
00799     chunk, reinterpret_cast<T_PIXEL*>(chunk->data()),
00800     ni, nj, np, 1, ni, ni*nj);
00801 
00802   for ( unsigned int p = 0; p < np; ++p )
00803   {
00804     T_PIXEL sign = opj_view_t->comps[p].sgnd ?
00805                    1 << (opj_view_t->comps[p].prec - 1) : 0;
00806 
00807     int *src_plane = opj_view_t->comps[p].data;
00808     T_PIXEL *dst_plane = vil_view_t->begin() + p*vil_view_t->planestep();
00809 
00810     for ( unsigned int j = 0; j < nj; ++j)
00811     {
00812       int *src_row = src_plane + (j0+j)*opj_view_t->comps[p].w + i0;
00813       T_PIXEL *dst_row = dst_plane + j*vil_view_t->jstep();
00814 
00815       for ( unsigned int i = 0; i < ni; ++i )
00816       {
00817         *(dst_row + i*vil_view_t->istep()) = src_row[i] + sign;
00818       }
00819     }
00820   }
00821 
00822   return vil_view_t;
00823 }
00824 
00825 
00826 bool
00827 vil_openjpeg_image
00828 ::put_view(const vil_image_view_base& im, unsigned int i0, unsigned int j0)
00829 {
00830   return false;
00831 }
00832 
00833 
00834 bool
00835 vil_openjpeg_image
00836 ::get_property(char const* tag, void* property_value) const
00837 {
00838   return false;
00839 }
00840