00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008
00009
00010
00011 #include "vil1_iris.h"
00012
00013 #include <vcl_cassert.h>
00014 #include <vcl_cstring.h>
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);
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 get_ushort(is);
00046 get_ushort(is);
00047 get_ushort(is);
00048 get_long(is);
00049 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 ):
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
00166
00167
00168 is_->seek(24L);
00169 is_->read(imagename_, 80L);
00170
00171
00172 colormap_ = get_long(is_);
00173
00174
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_)
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_);
00232 send_char(is_, bytes_per_component_);
00233 send_ushort(is_, dimension_);
00234 send_ushort(is_, width_);
00235 send_ushort(is_, height_);
00236 send_ushort(is_, planes_);
00237 send_long(is_, pixmin_);
00238 send_long(is_, pixmax_);
00239 is_->write(dummy, 4L);
00240 is_->write(imagename_, 80L);
00241 send_long(is_, colormap_);
00242
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
00261
00262 assert(x0>=0);
00263
00264 assert((x0+xs)<=width_);
00265 assert((y0+ys)<=height_);
00266
00267 if (!buf) return false;
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
00286 cbi+=(row_len*(ys-1));
00287
00288 is_->seek(512L + channel * width_ * height_ + (y0 * width_) + x0);
00289
00290
00291 int skipbytes_end = width_ - xs;
00292
00293
00294 for (int row = 0; row < ys; ++row,cbi-=row_len)
00295 {
00296
00297 if (row > 0) is_->seek(is_->tell() + skipbytes_end);
00298 is_->read(cbi, row_len);
00299 }
00300 }
00301 return true;
00302 }
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
00313 for (int channel=0; channel<planes_; ++channel)
00314 {
00315 unsigned char* cbi = dp + row_len*ys*channel;
00316
00317 cbi+=row_len*(ys-1);
00318
00319
00320 for (int rowno=y0; rowno<y0+ys; ++rowno,cbi-=row_len)
00321 {
00322
00323 unsigned long rleoffset = starttab_[rowno+channel*height_];
00324 unsigned long rlelength = lengthtab_[rowno+channel*height_];
00325
00326
00327 unsigned char* rlerow = new unsigned char[rlelength];
00328 is_->seek(rleoffset);
00329 is_->read((void*)rlerow, rlelength);
00330
00331
00332 expandrow(exrow,rlerow,0);
00333 delete[] rlerow;
00334
00335
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
00351 for (int channel=0; channel<planes_; ++channel)
00352 {
00353 const unsigned char* cbi = (const unsigned char*)buf + row_len*ys*channel;
00354
00355 cbi+=row_len*(ys-1);
00356
00357
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
00364 for (int row = 0; row < ys; ++row,cbi-=row_len)
00365 {
00366
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 }