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 #include "vil_iris.h"
00019
00020 #include <vcl_cassert.h>
00021 #include <vcl_cstring.h>
00022 #include <vcl_iostream.h>
00023
00024 #include <vil/vil_stream.h>
00025 #include <vil/vil_image_view.h>
00026 #include <vil/vil_exception.h>
00027
00028 #include <vxl_config.h>
00029
00030 static vxl_sint_16 get_short(vil_stream* file, int location = -1);
00031 static vxl_uint_16 get_ushort(vil_stream* file, int location = -1);
00032 static char get_char(vil_stream* file, int location = -1);
00033 static vxl_sint_32 get_long(vil_stream* file, int location = -1);
00034 static void send_char(vil_stream* data, char s);
00035 static void send_short(vil_stream* data, vxl_sint_16 s);
00036 static void send_ushort(vil_stream* data, vxl_uint_16 s);
00037 static void send_long(vil_stream* data, vxl_sint_32 s);
00038 static void expandrow(unsigned char *optr, unsigned char *iptr, int z);
00039
00040 char const* vil_iris_format_tag = "iris";
00041
00042 vil_image_resource_sptr vil_iris_file_format::make_input_image(vil_stream* is)
00043 {
00044 is->seek(0L);
00045 if (is->file_size() < 84L) return 0;
00046 int colormap_;
00047
00048 vxl_sint_16 magic_ = get_short(is);
00049 int storage_ = get_char(is);
00050 int bytes_per_component = get_char(is);
00051 int dimension_ = get_ushort(is);
00052 get_ushort(is);
00053 get_ushort(is);
00054 get_ushort(is);
00055 get_long(is);
00056 get_long(is);
00057
00058 is->seek(24L);
00059 char imagename[81];
00060 if (is->read(imagename, 80L) != 80) return 0;
00061
00062 colormap_ = get_long(is);
00063
00064 if (magic_ != 474) return 0;
00065 if (storage_ != 0 && storage_ != 1) return 0;
00066 if (colormap_ == 3) return 0;
00067 if (dimension_ == 3 && colormap_ != 0) return 0;
00068 if (dimension_ > 3 || dimension_ < 1) return 0;
00069 if (bytes_per_component < 1 || bytes_per_component > 2) return 0;
00070
00071 return new vil_iris_generic_image(is,imagename);
00072 }
00073
00074 vil_image_resource_sptr vil_iris_file_format::make_output_image(vil_stream* is,
00075 unsigned int ni, unsigned int nj, unsigned int nplanes,
00076 vil_pixel_format format)
00077 {
00078 return new vil_iris_generic_image(is, ni, nj, nplanes, format);
00079 }
00080
00081 char const* vil_iris_file_format::tag() const
00082 {
00083 return vil_iris_format_tag;
00084 }
00085
00086
00087
00088 vil_iris_generic_image::vil_iris_generic_image(vil_stream* is, char const* imagename):
00089 starttab_(0), lengthtab_(0), is_(is)
00090 {
00091 is_->ref();
00092 read_header();
00093 vcl_strncpy(imagename_, imagename, 80);
00094 }
00095
00096 bool vil_iris_generic_image::get_property(char const* , void* ) const
00097 {
00098
00099 return false;
00100 }
00101
00102 char const* vil_iris_generic_image::file_format() const
00103 {
00104 return vil_iris_format_tag;
00105 }
00106
00107 vil_iris_generic_image::vil_iris_generic_image(vil_stream* is,
00108 unsigned int ni, unsigned int nj, unsigned int nplanes,
00109 vil_pixel_format format)
00110 : starttab_(0), lengthtab_(0), is_(is), magic_(474), ni_(ni), nj_(nj),
00111 nplanes_(nplanes), format_(format), pixmin_(0),
00112 pixmax_(vil_pixel_format_sizeof_components(format)==1 ? 255 : 65535),
00113 storage_(0), dimension_(nplanes_==1 ? 2 : 3), colormap_(0)
00114 {
00115 is_->ref();
00116
00117 if (vil_pixel_format_sizeof_components(format) <= 2)
00118 {
00119 vcl_strcpy(imagename_, "written by vil_iris_generic_image");
00120
00121 if (nplanes_ != 1 && nplanes_ != 3 && nplanes_ != 4)
00122 vcl_cerr << __FILE__ ": Cannot write iris image, can only do grayscale or RGB(A)\n";
00123 write_header();
00124 }
00125 else vcl_cerr << __FILE__ ": Cannot write iris image, which needs 8 or 16 bits per component\n";
00126 }
00127
00128 vil_iris_generic_image::~vil_iris_generic_image()
00129 {
00130 is_->unref();
00131 delete [] starttab_;
00132 delete [] lengthtab_;
00133 }
00134
00135 bool vil_iris_generic_image::read_header()
00136 {
00137 is_->seek(0L);
00138
00139 magic_ = get_short(is_, 0);
00140 if (magic_ != 474)
00141 {
00142 vcl_cerr << __FILE__ ": This is not an Iris RGB file: magic number is incorrect: "
00143 << magic_ << vcl_endl;
00144 return false;
00145 }
00146
00147 storage_ = get_char(is_);
00148 if (storage_ != 0 && storage_ != 1)
00149 {
00150 vcl_cerr << __FILE__ ": This is not an Iris RGB file: storage must be RLE or VERBATIM\n";
00151 return false;
00152 }
00153
00154 int bytes_per_component = get_char(is_);
00155 dimension_ = get_ushort(is_);
00156 ni_ = get_ushort(is_);
00157 nj_ = get_ushort(is_);
00158 nplanes_ = get_ushort(is_);
00159 pixmin_ = get_long(is_);
00160 pixmax_ = get_long(is_);
00161 format_ = bytes_per_component==1 ? VIL_PIXEL_FORMAT_BYTE :
00162 bytes_per_component==2 ? VIL_PIXEL_FORMAT_UINT_16 :
00163 VIL_PIXEL_FORMAT_UNKNOWN;
00164
00165
00166
00167
00168 is_->seek(24L);
00169 is_->read(imagename_, 80L);
00170
00171
00172 colormap_ = get_long(is_);
00173
00174
00175
00176 if (colormap_ == 3)
00177 {
00178 vcl_cerr << __FILE__ ": This is not an ordinary Iris RGB image but a colormap file which I cannot handle\n";
00179 return false;
00180 }
00181
00182 if (dimension_ == 3 && colormap_ != 0)
00183 {
00184 vcl_cerr << __FILE__ ": Cannot handle Iris RGB file with colormap other than NORMAL\n";
00185 return false;
00186 }
00187
00188 if (storage_)
00189 read_offset_tables();
00190
00191 return true;
00192 }
00193
00194
00195 bool vil_iris_generic_image::write_header()
00196 {
00197 #ifdef DEBUG
00198 vcl_cerr << __FILE__ ": vil_iris_generic_image::write_header()\n"
00199 << "Here we go :\n"
00200 << "magic_ = " << magic_ << vcl_endl
00201 << "storage_ = " << storage_ << vcl_endl
00202 << "format_ = " << format_ << vcl_endl
00203 << "dimension_ = " << dimension_ << vcl_endl
00204 << "ni_ = " << ni_ << vcl_endl
00205 << "nj_ = " << nj_ << vcl_endl
00206 << "nplanes_ = " << nplanes_ << vcl_endl
00207 << "pixmin_ = " << pixmin_ << vcl_endl
00208 << "pixmax_ = " << pixmax_ << vcl_endl
00209 << "colormap_ = " << colormap_ << vcl_endl
00210 << "imagename_ = " << imagename_ << vcl_endl
00211 << vcl_endl;
00212 #endif
00213
00214 char dummy[410];
00215
00216 send_short(is_, static_cast<vxl_sint_16>(magic_));
00217 send_char(is_, (char)storage_);
00218 send_char(is_, (char)vil_pixel_format_sizeof_components(format_));
00219 send_ushort(is_, static_cast<vxl_uint_16>(dimension_));
00220 send_ushort(is_, static_cast<vxl_uint_16>(ni_));
00221 send_ushort(is_, static_cast<vxl_uint_16>(nj_));
00222 send_ushort(is_, static_cast<vxl_uint_16>(nplanes_));
00223 send_long(is_, pixmin_);
00224 send_long(is_, pixmax_);
00225 is_->write(dummy, 4L);
00226 is_->write(imagename_, 80L);
00227 send_long(is_, colormap_);
00228
00229
00230 start_of_data_ = is_->tell();
00231
00232 return is_->write(dummy, 404L) == 404L;
00233 }
00234
00235
00236 static inline void swap(void* p,int length)
00237 {
00238 char* t = (char*)p;
00239 #ifdef DEBUG
00240 if (length == sizeof(vxl_uint_32) && *(vxl_uint_32*)p != 0) {
00241 vcl_cerr << "Swapping " << *(vxl_uint_32*)p;
00242 if (length == sizeof(float))
00243 vcl_cerr << " (or " << *(float*)p << ')';
00244 }
00245 #endif
00246 for (int j=0;2*j<length;++j) { char c = t[j]; t[j] = t[length-j-1]; t[length-j-1] = c; }
00247 #ifdef DEBUG
00248 if (length == sizeof(vxl_uint_32) && *(vxl_uint_32*)p != 0) {
00249 vcl_cerr << " to " << *(vxl_uint_32*)p;
00250 if (length == sizeof(float))
00251 vcl_cerr << " (or " << *(float*)p << ')';
00252 vcl_cerr << '\n';
00253 }
00254 #endif
00255 }
00256
00257 vil_image_view_base_sptr vil_iris_generic_image::get_copy_view( unsigned int x0, unsigned int xs,
00258 unsigned int y0, unsigned int ys) const
00259 {
00260
00261
00262 assert(x0+xs<=ni_);
00263 assert(y0+ys<=nj_);
00264
00265 if (storage_)
00266 return get_section_rle(x0,xs,y0,ys);
00267 else
00268 return get_section_verbatim(x0,xs,y0,ys);
00269 }
00270
00271
00272 vil_image_view_base_sptr vil_iris_generic_image::get_section_verbatim(unsigned int x0, unsigned int xs,
00273 unsigned int y0, unsigned int ys) const
00274 {
00275 unsigned int pix_size = vil_pixel_format_sizeof_components(format_);
00276 unsigned int row_len = xs * pix_size;
00277
00278 vil_memory_chunk_sptr buf = new vil_memory_chunk(row_len*ys*nplanes_,format_);
00279 vxl_byte* ib = reinterpret_cast<vxl_byte*>(buf->data());
00280 vxl_uint_16* ob = reinterpret_cast<vxl_uint_16*>(buf->data());
00281 vxl_byte* cbi = ib;
00282
00283
00284 for (unsigned int channel=0; channel<nplanes_; ++channel)
00285 {
00286
00287 for (unsigned int row = nj_-y0-ys; row < nj_-y0; ++row,cbi+=row_len)
00288 {
00289 is_->seek(512L + (channel * ni_*nj_ + row * ni_ + x0) * pix_size);
00290 is_->read(cbi, row_len);
00291 }
00292 }
00293 if (VXL_LITTLE_ENDIAN && pix_size > 1)
00294 for (unsigned int i=0;i<xs*ys*nplanes_;++i)
00295 swap(ob+i,pix_size);
00296
00297
00298 if (format_ == VIL_PIXEL_FORMAT_BYTE)
00299 return new vil_image_view<vxl_byte>(buf,ib+xs*(ys-1),xs,ys,nplanes_,1,-int(xs),xs*ys);
00300 else if (format_ == VIL_PIXEL_FORMAT_UINT_16)
00301 return new vil_image_view<vxl_uint_16>(buf,ob+xs*(ys-1),xs,ys,nplanes_,1,-int(xs),xs*ys);
00302 else
00303 return 0;
00304 }
00305
00306
00307 vil_image_view_base_sptr vil_iris_generic_image::get_section_rle(unsigned int x0, unsigned int xs,
00308 unsigned int y0, unsigned int ys) const
00309 {
00310 unsigned int pix_size = vil_pixel_format_sizeof_components(format_);
00311 unsigned int row_len = xs * pix_size;
00312
00313 vil_memory_chunk_sptr buf = new vil_memory_chunk(row_len*ys*nplanes_,format_);
00314 vxl_byte* ib = reinterpret_cast<vxl_byte*>(buf->data());
00315 vxl_uint_16* ob = reinterpret_cast<vxl_uint_16*>(buf->data());
00316 vxl_byte* cbi = ib;
00317 unsigned char* exrow = new unsigned char[ni_];
00318
00319
00320 for (unsigned int channel=0; channel<nplanes_; ++channel)
00321 {
00322
00323 for (unsigned int rowno=nj_-y0-ys; rowno<nj_-y0; ++rowno,cbi+=row_len)
00324 {
00325
00326 unsigned long rleoffset = starttab_[rowno+channel*nj_];
00327 unsigned long rlelength = lengthtab_[rowno+channel*nj_];
00328
00329
00330 unsigned char* rlerow = new unsigned char[rlelength];
00331 is_->seek(rleoffset);
00332 is_->read((void*)rlerow, rlelength);
00333
00334
00335 expandrow(exrow,rlerow,0);
00336 delete[] rlerow;
00337
00338
00339 vcl_memcpy(cbi,exrow+x0,xs);
00340 }
00341 }
00342 delete[] exrow;
00343 if (format_ == VIL_PIXEL_FORMAT_BYTE)
00344 return new vil_image_view<vxl_byte>(buf,ib+xs*(ys-1),xs,ys,nplanes_,1,-int(xs),xs*ys);
00345 else if (format_ == VIL_PIXEL_FORMAT_UINT_16)
00346 return new vil_image_view<vxl_uint_16>(buf,ob+xs*(ys-1),xs,ys,nplanes_,1,-int(xs),xs*ys);
00347 else
00348 return 0;
00349 }
00350
00351
00352 bool vil_iris_generic_image::put_view( vil_image_view_base const& buf, unsigned int x0, unsigned int y0)
00353 {
00354 assert(buf.pixel_format() == format_);
00355 if (!view_fits(buf, x0, y0))
00356 {
00357 vil_exception_warning(vil_exception_out_of_bounds("vil_iris_generic_image::put_view"));
00358 return false;
00359 }
00360 #ifdef DEBUG
00361 vcl_cerr << "vil_iris_image::put_view() : buf="
00362 << buf.ni()<<'x'<<buf.nj()<<'x'<< buf.nplanes()<<'p'
00363 << " at ("<<x0<<','<<y0<<")\n";
00364 #endif
00365 const vil_image_view<unsigned char>& buff = static_cast<vil_image_view<unsigned char> const&>(buf);
00366 const unsigned char* ob = buff.top_left_ptr();
00367 unsigned int pix_size = vil_pixel_format_sizeof_components(format_);
00368
00369 vcl_size_t rowsize = pix_size*buf.ni();
00370 vcl_ptrdiff_t rowskip = pix_size*buff.jstep();
00371 vcl_size_t planeskip = pix_size*buff.planestep();
00372
00373 if (VXL_LITTLE_ENDIAN && pix_size > 1)
00374 {
00375
00376 vxl_byte* tempbuf = new vxl_byte[rowsize];
00377
00378 for (unsigned int channel = 0; channel<nplanes_; ++channel) {
00379 ob += rowskip*buff.nj();
00380
00381 for (unsigned int y = nj_-y0-buf.nj(); y < nj_-y0; ++y) {
00382 ob -= rowskip;
00383
00384 is_->seek(512L + (channel * ni_*nj_ + y * ni_ + x0) * pix_size);
00385
00386 vcl_memcpy(tempbuf,ob,rowsize);
00387 for (unsigned int i=0;i<buf.ni();++i)
00388 swap(tempbuf+i*pix_size,pix_size);
00389
00390 if ((vil_streampos)rowsize != is_->write(tempbuf, rowsize))
00391 vcl_cerr << "WARNING: " << __FILE__ << ":\n"
00392 << " could not write "<<rowsize<<" bytes to stream;\n"
00393 << " channel="<<channel<<", y="<<y<<'\n';
00394 #ifdef DEBUG
00395 else
00396 vcl_cerr << "written "<<rowsize<<" bytes to stream; channel="<<channel<<", y="<<y<<'\n';
00397 #endif
00398 }
00399 ob += planeskip;
00400 }
00401 delete[] tempbuf;
00402 }
00403 else
00404 {
00405
00406 for (unsigned int channel = 0; channel<nplanes_; ++channel) {
00407 ob += rowskip*buff.nj();
00408
00409 for (unsigned int y = nj_-y0-buf.nj(); y < nj_-y0; ++y) {
00410 ob -= rowskip;
00411
00412 is_->seek(512L + (channel * ni_*nj_ + y * ni_ + x0) * pix_size);
00413 if ((vil_streampos)rowsize != is_->write(ob, rowsize))
00414 vcl_cerr << "WARNING: " << __FILE__ << ":\n"
00415 << " could not write "<<rowsize<<" bytes to stream;\n"
00416 << " channel="<<channel<<", y="<<y<<'\n';
00417 #ifdef DEBUG
00418 else
00419 vcl_cerr << "written "<<rowsize<<" bytes to stream; channel="<<channel<<", y="<<y<<'\n';
00420 #endif
00421 }
00422 ob += planeskip;
00423 }
00424 }
00425 return true;
00426 }
00427
00428 bool vil_iris_generic_image::read_offset_tables()
00429 {
00430 unsigned int tablen = nj_ * nplanes_;
00431
00432 starttab_ = new unsigned long[tablen];
00433 lengthtab_ = new unsigned long[tablen];
00434
00435 for (unsigned int i=0; i<tablen; ++i) {
00436 starttab_[i] = get_long(is_,512+(i*4));
00437 }
00438
00439 unsigned int lengthtab_offset = 512 + tablen*4;
00440
00441 for (unsigned int i=0; i<tablen; ++i) {
00442 lengthtab_[i] = get_long(is_,lengthtab_offset+(i*4));
00443 }
00444
00445 return true;
00446 }
00447
00448
00449 vxl_sint_16 get_short(vil_stream* file, int location)
00450 {
00451 if (location >= 0) file->seek(location);
00452
00453 vxl_byte buff[2];
00454 file->read(buff, 2L);
00455
00456
00457 vxl_uint_16 bits = static_cast<vxl_uint_16>(( buff[0] << 8 ) + buff[1]);
00458
00459 if ( ( bits & 0x8000 ) != 0 )
00460 return static_cast<vxl_sint_16>(-( ~bits + 1 ));
00461 else
00462 return static_cast<vxl_sint_16>( bits );
00463 }
00464
00465
00466 char get_char(vil_stream* file, int location)
00467 {
00468 if (location >= 0) file->seek(location);
00469
00470 char buff[1];
00471 file->read((void*)buff, 1L);
00472 return buff[0];
00473 }
00474
00475 vxl_uint_16 get_ushort(vil_stream* file, int location)
00476 {
00477 if (location >= 0) file->seek(location);
00478
00479 unsigned char buff[2];
00480 file->read((void*)buff, 2L);
00481 return static_cast<vxl_uint_16>((buff[0]<<8)+(buff[1]<<0));
00482 }
00483
00484 vxl_sint_32 get_long(vil_stream* file, int location)
00485 {
00486 if (location >= 0) file->seek(location);
00487
00488 vxl_byte buff[4];
00489 if (file->read((void*)buff, 4L) != 4L) return 0;
00490
00491
00492 vxl_uint_32 bits = ( vxl_uint_32(buff[0]) << 24 ) |
00493 ( vxl_uint_32(buff[1]) << 16 ) |
00494 ( vxl_uint_32(buff[2]) << 8 ) |
00495 buff[3];
00496
00497 if ( ( bits & 0x80000000L ) != 0 )
00498 return -vxl_sint_32( ~bits + 1 );
00499 else
00500 return vxl_sint_32( bits );
00501 }
00502
00503
00504 void send_char(vil_stream* data, char s)
00505 {
00506 data->write(&s ,1L);
00507 }
00508
00509 void send_short(vil_stream* data, vxl_sint_16 s)
00510 {
00511 vxl_uint_16 bits;
00512 if ( s < 0 ) {
00513 bits = static_cast<vxl_uint_16>(-s);
00514 bits = static_cast<vxl_uint_16>(~bits + 1);
00515 }
00516 else {
00517 bits = static_cast<vxl_uint_16>(s);
00518 }
00519
00520 vxl_byte buff[2];
00521 buff[0] = static_cast<vxl_byte>((bits >> 8) & 0xff);
00522 buff[1] = static_cast<vxl_byte>( bits & 0xff);
00523 data->write(buff, 2L);
00524 }
00525
00526 void send_ushort(vil_stream* data, vxl_uint_16 s)
00527 {
00528 unsigned char buff[2];
00529 buff[0] = static_cast<unsigned char>((s >> 8) & 0xff);
00530 buff[1] = static_cast<unsigned char>( s & 0xff);
00531 data->write(buff, 2L);
00532 }
00533
00534 void send_long(vil_stream* data, vxl_sint_32 s)
00535 {
00536
00537
00538 vxl_uint_32 bits;
00539 if ( s < 0 ) {
00540 bits = -s;
00541 bits = ~bits + 1;
00542 }
00543 else {
00544 bits = s;
00545 }
00546
00547 vxl_byte buff[4];
00548 buff[0] = static_cast<unsigned char>( (bits >> 24) & 0xff );
00549 buff[1] = static_cast<unsigned char>( (bits >> 16) & 0xff );
00550 buff[2] = static_cast<unsigned char>( (bits >> 8) & 0xff );
00551 buff[3] = static_cast<unsigned char>( bits & 0xff );
00552 data->write(buff, 4L);
00553 }
00554
00555 void expandrow(unsigned char *optr, unsigned char *iptr, int z)
00556 {
00557 unsigned char pixel, count;
00558
00559 optr += z;
00560 while (true)
00561 {
00562 pixel = *iptr++;
00563 if ( !(count = static_cast<unsigned char>(pixel & 0x7f)) )
00564 return;
00565 if (pixel & 0x80)
00566 {
00567 while (count--) { *optr = *iptr++; ++optr; }
00568 }
00569 else
00570 {
00571 pixel = *iptr++;
00572 while (count--) { *optr = pixel; ++optr; }
00573 }
00574 }
00575 }