core/vil1/file_formats/vil1_iris.cxx

Go to the documentation of this file.
00001 // This is core/vil1/file_formats/vil1_iris.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //
00006 // Author: Joris Schouteden
00007 // Created: 17 Feb 2000
00008 //
00009 //-----------------------------------------------------------------------------
00010 
00011 #include "vil1_iris.h"
00012 
00013 #include <vcl_cassert.h>
00014 #include <vcl_cstring.h> // for memcpy()
00015 #include <vcl_iostream.h>
00016 
00017 #include <vil1/vil1_stream.h>
00018 #include <vil1/vil1_image_impl.h>
00019 #include <vil1/vil1_image.h>
00020 #include <vil1/vil1_property.h>
00021 
00022 static short get_short(vil1_stream* file, int location = -1); // default -1 means: read at current position
00023 static unsigned short get_ushort(vil1_stream* file, int location = -1);
00024 static char get_char(vil1_stream* file, int location = -1);
00025 static long get_long(vil1_stream* file, int location = -1);
00026 static void send_char(vil1_stream* data, int s);
00027 static void send_short(vil1_stream* data, int s);
00028 static void send_ushort(vil1_stream* data, unsigned int s);
00029 static void send_long(vil1_stream* data, long s);
00030 static void expandrow(unsigned char *optr, unsigned char *iptr, int z);
00031 
00032 
00033 char const* vil1_iris_format_tag = "iris";
00034 
00035 vil1_image_impl* vil1_iris_file_format::make_input_image(vil1_stream* is)
00036 {
00037   is->seek(0L);
00038 
00039   int colormap_;
00040 
00041   int magic_     = get_short(is);
00042   int storage_   = get_char(is);
00043   int bytes_per_component_ = get_char(is);
00044   int dimension_ = get_ushort(is);
00045   /*int width_     =*/ get_ushort(is);
00046   /*int height_    =*/ get_ushort(is);
00047   /*int planes_    =*/ get_ushort(is);
00048   /*int pixmin_    =*/ get_long(is);
00049   /*int pixmax_    =*/ get_long(is);
00050 
00051   is->seek(24L);
00052   char imagename[81];
00053   is->read(imagename, 80L);
00054 
00055   colormap_ = get_long(is);
00056 
00057   if (magic_ != 474) return 0;
00058   if (storage_ != 0 && storage_ != 1) return 0;
00059   if (colormap_ == 3) return 0;
00060   if (dimension_ == 3 && colormap_ != 0) return 0;
00061   if (dimension_ > 3 || dimension_ < 1) return 0;
00062   if (bytes_per_component_ < 1 || bytes_per_component_ > 2) return 0;
00063 
00064   return new vil1_iris_generic_image(is,imagename);
00065 }
00066 
00067 vil1_image_impl* vil1_iris_file_format::make_output_image(vil1_stream* is, int planes,
00068                                                           int width,
00069                                                           int height,
00070                                                           int components,
00071                                                           int bits_per_component,
00072                                                           vil1_component_format format)
00073 {
00074   return new vil1_iris_generic_image(is, planes, width, height, components, bits_per_component, format);
00075 }
00076 
00077 char const* vil1_iris_file_format::tag() const
00078 {
00079   return vil1_iris_format_tag;
00080 }
00081 
00082 /////////////////////////////////////////////////////////////////////////////
00083 
00084 vil1_iris_generic_image::vil1_iris_generic_image(vil1_stream* is, char* imagename):
00085   starttab_(0), lengthtab_(0), is_(is)
00086 {
00087   is_->ref();
00088   read_header();
00089   vcl_strncpy(imagename_, imagename, 80);
00090 }
00091 
00092 bool vil1_iris_generic_image::get_property(char const *tag, void *prop) const
00093 {
00094   if (0==vcl_strcmp(tag, vil1_property_top_row_first))
00095     return prop ? (*(bool*)prop) = true : true;
00096 
00097   if (0==vcl_strcmp(tag, vil1_property_left_first))
00098     return prop ? (*(bool*)prop) = true : true;
00099 
00100   return false;
00101 }
00102 
00103 char const* vil1_iris_generic_image::file_format() const
00104 {
00105   return vil1_iris_format_tag;
00106 }
00107 
00108 vil1_iris_generic_image::vil1_iris_generic_image(vil1_stream* is, int planes,
00109                                                  int width,
00110                                                  int height,
00111                                                  int components,
00112                                                  int bits_per_component,
00113                                                  vil1_component_format /*format*/):
00114   starttab_(0), lengthtab_(0), is_(is)
00115 {
00116   is_->ref();
00117 
00118   if (bits_per_component == 8 ||
00119       bits_per_component == 16)
00120   {
00121     magic_  = 474;
00122     storage_ = 0;
00123     bytes_per_component_ = bits_per_component / 8;
00124     width_  = width;
00125     height_ = height;
00126     pixmin_ = 0;
00127     pixmax_ = (bits_per_component == 8) ? 255 : 65535;
00128     vcl_strcpy(imagename_, "vil1 writes an iris image!");
00129     colormap_ = 0;
00130 
00131     components_ = 1;
00132     planes_ = components * planes;
00133     if (planes_ == 1)
00134       dimension_ = 2;
00135     else if (planes_ == 3 || planes_ == 4)
00136       dimension_ = 3;
00137     else vcl_cerr << __FILE__ ": Cannot write iris image, they can only do grayscale or RGB(A)\n";
00138     write_header();
00139   }
00140   else vcl_cerr << __FILE__ ": Cannot write iris image, they want 8 or 16 bits per component\n";
00141 }
00142 
00143 vil1_iris_generic_image::~vil1_iris_generic_image()
00144 {
00145   is_ -> unref();
00146   delete[] starttab_;
00147   delete[] lengthtab_;
00148 }
00149 
00150 bool vil1_iris_generic_image::read_header()
00151 {
00152   is_->seek(0L);
00153 
00154   magic_     = get_short(is_, 0);
00155   storage_   = get_char(is_);
00156   bytes_per_component_ = get_char(is_);
00157   dimension_           = get_ushort(is_);
00158   width_     = get_ushort(is_);
00159   height_    = get_ushort(is_);
00160   planes_    = get_ushort(is_);
00161   pixmin_    = get_long(is_);
00162   pixmax_    = get_long(is_);
00163   components_ = 1;
00164 
00165   // DUMMY1 starts at 20
00166   //  starts at 24
00167 
00168   is_->seek(24L);
00169   is_->read(imagename_, 80L);
00170 
00171   // COLORMAP starts at 104
00172   colormap_ = get_long(is_);
00173 
00174   // _DUMMY2 starts at 108, ends at 512
00175 
00176   if (magic_ != 474)
00177   {
00178     vcl_cerr << __FILE__ ": This is not an Iris RGB file: magic number is incorrect: "
00179              << magic_ << vcl_endl;
00180     return false;
00181   }
00182 
00183   if (storage_ != 0 && storage_ != 1)
00184   {
00185     vcl_cerr << __FILE__ ": This is not an Iris RGB file: storage must be RLE or VERBATIM\n";
00186     return false;
00187   }
00188 
00189   if (colormap_ == 3)
00190   {
00191     vcl_cerr << __FILE__ ": This is not an ordinary Iris RGB image but a colormap file\n";
00192     return false;
00193   }
00194 
00195   if (dimension_ == 3 && colormap_ != 0)
00196   {
00197     vcl_cerr << __FILE__ ": Cannot handle Iris RGB file with colormap other than NORMAL\n";
00198     return false;
00199   }
00200 
00201   if (storage_)    // we got a RLE image
00202     read_offset_tables();
00203 
00204   return true;
00205 }
00206 
00207 
00208 bool vil1_iris_generic_image::write_header()
00209 {
00210 #ifdef DEBUG
00211   vcl_cerr << __FILE__ ": vil1_iris_generic_image::write_header()\n"
00212            << "Here we go :\n"
00213            << "magic_      = " << magic_    << vcl_endl
00214            << "storage_    = " << storage_ << vcl_endl
00215            << "bytes_per_c = " << bytes_per_component_ << vcl_endl
00216            << "dimension_  = " << dimension_ << vcl_endl
00217            << "width_      = " << width_ << vcl_endl
00218            << "height_     = " << height_ << vcl_endl
00219            << "planes_     = " << planes_ << vcl_endl
00220            << "pixmin_     = " << pixmin_ << vcl_endl
00221            << "pixmax_     = " << pixmax_ << vcl_endl
00222            << "colormap_   = " << colormap_ << vcl_endl
00223            << "components_ = " << components_ << vcl_endl
00224            << "imagename_  = " << imagename_ << vcl_endl
00225            << vcl_endl;
00226 #endif
00227 
00228   char dummy[410];
00229 
00230   send_short(is_, magic_);
00231   send_char(is_, storage_); // either VERBATIM (0) or RLE (1)
00232   send_char(is_, bytes_per_component_);  // bytes per pixel per channel
00233   send_ushort(is_, dimension_); // either 1 (1 scanline), 2 (grey image), or 3 (colour)
00234   send_ushort(is_, width_);    // width
00235   send_ushort(is_, height_);    // height
00236   send_ushort(is_, planes_);    // nr of colour bands; typically 3 (RGB) or 4 (RGBA)
00237   send_long(is_, pixmin_);   // minimum pixel value; typically 0
00238   send_long(is_, pixmax_); // maximum pixel value; typically 255 if _PBC is 1
00239   is_->write(dummy, 4L);
00240   is_->write(imagename_, 80L); // null-terminated string
00241   send_long(is_, colormap_); // either NORMAL (0) (RGB), DITHERED (1) (R=3,G=3,B=2 bits),
00242                   // SCREEN (2) (obsolete) or COLORMAP (3) (hardware-specific).
00243 
00244   start_of_data_ = is_->tell();
00245 
00246   return is_->write(dummy, 404L) == 404L;
00247 }
00248 
00249 
00250 vil1_image vil1_iris_generic_image::get_plane(unsigned int plane) const
00251 {
00252   assert((int)plane < planes_);
00253   vcl_cerr << __FILE__ ": do something for vil1_iris_generic_image::get_plane\n";
00254   return 0;
00255 }
00256 
00257 
00258 bool vil1_iris_generic_image::get_section(void* buf, int x0, int y0, int xs, int ys) const
00259 {
00260   // at the moment I am not dealing with requests for memory
00261   // outside the image so just abort if you get any
00262   assert(x0>=0);
00263 
00264   assert((x0+xs)<=width_);
00265   assert((y0+ys)<=height_);
00266 
00267   if (!buf) return false; // no storage location was given to us
00268 
00269   if (storage_)
00270     return get_section_rle(buf,x0,height_-y0-ys,xs,ys);
00271   else
00272     return get_section_verbatim(buf,x0,height_-y0-ys,xs,ys);
00273 }
00274 
00275 
00276 bool vil1_iris_generic_image::get_section_verbatim(void* ib, int x0, int y0, int xs, int ys) const
00277 {
00278   int row_len = xs * bytes_per_component_;
00279 
00280   unsigned char* dp = (unsigned char*)ib;
00281 
00282   for (int channel=0; channel<planes_; ++channel)
00283   {
00284     unsigned char* cbi = dp + row_len*ys*channel;
00285     // skip cbi to point at last row of section
00286     cbi+=(row_len*(ys-1));
00287 
00288     is_->seek(512L + channel * width_ * height_ + (y0 * width_) + x0);
00289                                         // actually: times cell size
00290 
00291     int skipbytes_end = width_ - xs; // bytes to skip, across consecutive rows
00292 
00293     // number of rows to read
00294     for (int row = 0; row < ys; ++row,cbi-=row_len)
00295     {
00296       // step to end of row and then to within next row, where next block begins
00297       if (row > 0) is_->seek(is_->tell() + skipbytes_end);
00298       is_->read(cbi, row_len);
00299     }
00300   }
00301   return true;
00302 }//GetSectionVERBATIM
00303 
00304 
00305 bool vil1_iris_generic_image::get_section_rle(void* ib, int x0, int y0, int xs, int ys) const
00306 {
00307   int row_len = xs * bytes_per_component_;
00308 
00309   unsigned char* dp = (unsigned char*)ib;
00310   unsigned char* exrow = new unsigned char[width_];
00311 
00312   // for each channel
00313   for (int channel=0; channel<planes_; ++channel)
00314   {
00315     unsigned char* cbi = dp + row_len*ys*channel;
00316     // skip cbi to point at last row of section
00317     cbi+=row_len*(ys-1);
00318 
00319     // for each row
00320     for (int rowno=y0; rowno<y0+ys; ++rowno,cbi-=row_len)
00321     {
00322       // find length and start position
00323       unsigned long rleoffset =  starttab_[rowno+channel*height_];
00324       unsigned long rlelength = lengthtab_[rowno+channel*height_];
00325 
00326       // read rle row into array
00327       unsigned char* rlerow = new unsigned char[rlelength];
00328       is_->seek(rleoffset);
00329       is_->read((void*)rlerow, rlelength);
00330 
00331       // decode rle row
00332       expandrow(exrow,rlerow,0);
00333       delete[] rlerow;
00334 
00335       // write expanded row in store
00336       vcl_memcpy(cbi,exrow+x0,xs);
00337     }
00338   }
00339   delete[] exrow;
00340   return true;
00341 }
00342 
00343 
00344 bool vil1_iris_generic_image::put_section(void const* buf, int x0, int y0, int xs, int ys)
00345 {
00346   int ynul = height_ - y0 - ys;
00347 
00348   int row_len = xs * bytes_per_component_;
00349 
00350   // for each channel
00351   for (int channel=0; channel<planes_; ++channel)
00352   {
00353     const unsigned char* cbi = (const unsigned char*)buf + row_len*ys*channel;
00354     // skip cbi to point at last row of section
00355     cbi+=row_len*(ys-1);
00356 
00357     // skip to start of section
00358     is_->seek(512 + channel * width_ * height_
00359               + ynul*width_*bytes_per_pixel() + x0*bytes_per_pixel());
00360 
00361     int skipbytes_end = width_ - xs;
00362 
00363     // number of rows to write
00364     for (int row = 0; row < ys; ++row,cbi-=row_len)
00365     {
00366       // step to end of row, and then to beginning of block on next row
00367       if (row > 0) is_->seek(is_->tell() + skipbytes_end);
00368       is_->write(cbi, row_len);
00369     }
00370   }
00371   return true;
00372 }
00373 
00374 bool vil1_iris_generic_image::read_offset_tables()
00375 {
00376   int tablen;
00377   tablen = height_ * planes_;
00378 
00379   starttab_  = new unsigned long[tablen];
00380   lengthtab_ = new unsigned long[tablen];
00381 
00382   int i;
00383   for (i=0; i<tablen; ++i) {
00384     starttab_[i] = get_long(is_,512+(i*4));
00385   }
00386 
00387   int lengthtab_offset =  512 + tablen*4;
00388 
00389   for (i=0; i<tablen; ++i) {
00390     lengthtab_[i] = get_long(is_,lengthtab_offset+(i*4));
00391   }
00392 
00393   return true;
00394 }
00395 
00396 
00397 short get_short(vil1_stream* file, int location)
00398 {
00399   if (location >= 0) file->seek(location);
00400 
00401   unsigned char buff[2];
00402   file->read(buff, 2L);
00403   return (buff[0]<<8)+(buff[1]<<0);
00404 }
00405 
00406 
00407 char get_char(vil1_stream* file, int location)
00408 {
00409   if (location >= 0) file->seek(location);
00410 
00411   unsigned char buff[1];
00412   file->read((void*)buff, 1L);
00413   return buff[0];
00414 }
00415 
00416 unsigned short get_ushort(vil1_stream* file, int location)
00417 {
00418   if (location >= 0) file->seek(location);
00419 
00420   unsigned char buff[2];
00421   file->read((void*)buff, 2L);
00422   return (buff[0]<<8)+(buff[1]<<0);
00423 }
00424 
00425 long get_long(vil1_stream* file, int location)
00426 {
00427   if (location >= 0) file->seek(location);
00428 
00429   unsigned char buff[4];
00430   file->read((void*)buff, 4L);
00431   return (buff[0]<<24)+(buff[1]<<16)+(buff[2]<<8)+(buff[3]<<0);
00432 }
00433 
00434 
00435 void send_char(vil1_stream* data, int s)
00436 {
00437   char c = s;
00438   data->write(&c ,1L);
00439 }
00440 
00441 void send_short(vil1_stream* data, int s)
00442 {
00443   unsigned char buff[2];
00444   buff[0] = (s >> 8) & 0xff;
00445   buff[1] = (s >> 0) & 0xff;
00446   data->write(buff, 2L);
00447 }
00448 
00449 void send_ushort(vil1_stream* data, unsigned int s)
00450 {
00451   unsigned char buff[2];
00452   buff[0] = (s >> 8) & 0xff;
00453   buff[1] = (s >> 0) & 0xff;
00454   data->write(buff, 2L);
00455 }
00456 
00457 void send_long(vil1_stream* data, long s)
00458 {
00459   unsigned char buff[4];
00460   buff[0] = (unsigned char)((s >> 24) & 0xff);
00461   buff[1] = (unsigned char)((s >> 16) & 0xff);
00462   buff[2] = (unsigned char)((s >>  8) & 0xff);
00463   buff[3] = (unsigned char)((s >>  0) & 0xff);
00464   data->write(buff, 4L);
00465 }
00466 
00467 void expandrow(unsigned char *optr, unsigned char *iptr, int z)
00468 {
00469   unsigned char pixel, count;
00470 
00471   optr += z;
00472   while (true)
00473   {
00474     pixel = *iptr++;
00475     if ( !(count = (pixel & 0x7f)) )
00476       return;
00477     if (pixel & 0x80)
00478     {
00479       while (count--) { *optr = *iptr++; ++optr; }
00480     }
00481     else
00482     {
00483       pixel = *iptr++;
00484       while (count--) { *optr = pixel; ++optr; }
00485     }
00486   }
00487 }

Generated on Sat Nov 22 05:08:28 2008 for core/vil1 by  doxygen 1.5.1