00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "vil_mit.h"
00010
00011 static char const* vil_mit_format_tag = "mit";
00012
00013 #include <vcl_iostream.h>
00014 #include <vcl_cassert.h>
00015 #include <vcl_cstring.h>
00016
00017 #include <vil/vil_stream.h>
00018 #include <vil/vil_image_resource.h>
00019 #include <vil/vil_image_view.h>
00020 #include <vil/vil_stream_read.h>
00021 #include <vil/vil_stream_write.h>
00022 #include <vil/vil_exception.h>
00023
00024 #define MIT_UNSIGNED 0x0001
00025 #define MIT_RGB 0x0002
00026 #define MIT_HSB 0x0003
00027 #define MIT_CAP 0x0004
00028 #define MIT_SIGNED 0x0005
00029 #define MIT_FLOAT 0x0006
00030 #define MIT_EDGE 0x0007
00031
00032 #define MIT_UCOMPLEX 0x0101
00033 #define MIT_SCOMPLEX 0x0105
00034 #define MIT_FCOMPLEX 0x0106
00035
00036 #define MIT_UNSIGNED_E 0x0201
00037 #define MIT_SIGNED_E 0x0205
00038 #define MIT_FLOAT_E 0x0206
00039
00040 #define MIT_UCOMPLEX_E 0x0301
00041 #define MIT_SCOMPLEX_E 0x0305
00042 #define MIT_FCOMPLEX_E 0x0306
00043
00044 #define EDGE_HOR 0200
00045 #define EDGE_VER 0100
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 vil_image_resource_sptr vil_mit_file_format::make_input_image(vil_stream* is)
00061 {
00062 is->seek(0L);
00063 if (is->file_size() < 8L) return 0;
00064 unsigned int type = vil_stream_read_little_endian_uint_16(is);
00065
00066 if (!(type == MIT_UNSIGNED ||
00067 type == MIT_RGB ||
00068 type == MIT_SIGNED ||
00069 type == MIT_FLOAT ))
00070 return 0;
00071
00072 unsigned int bpp = vil_stream_read_little_endian_uint_16(is);
00073 if (bpp != 1 && bpp != 8 && bpp != 16 && bpp != 32 && bpp != 64)
00074 return 0;
00075
00076 #ifdef DEBUG
00077 unsigned int width = vil_stream_read_little_endian_uint_16(is);
00078 unsigned int height= vil_stream_read_little_endian_uint_16(is);
00079 vcl_cerr << __FILE__ " : here we go:\n"
00080 << __FILE__ " : type_ = " << type << vcl_endl
00081 << __FILE__ " : bits_per_pixel_ = " << bpp << vcl_endl
00082 << __FILE__ " : width_ = " << width << vcl_endl
00083 << __FILE__ " : height_ = " << height << vcl_endl;
00084 #endif
00085 return new vil_mit_image(is);
00086 }
00087
00088 vil_image_resource_sptr vil_mit_file_format::make_output_image(vil_stream* is,
00089 unsigned int ni, unsigned int nj, unsigned int nplanes,
00090 vil_pixel_format format)
00091 {
00092 return new vil_mit_image(is, ni, nj, nplanes, format);
00093 }
00094
00095 char const* vil_mit_file_format::tag() const
00096 {
00097 return vil_mit_format_tag;
00098 }
00099
00100
00101
00102 vil_mit_image::vil_mit_image(vil_stream* is)
00103 : is_(is)
00104 {
00105 is_->ref();
00106 if (!read_header())
00107 {
00108 vcl_cerr << "vil_mit: cannot read file header; creating dummy 0x0 image\n";
00109 ni_ = nj_ = 0; components_ = 1; type_ = 1;
00110 format_ = VIL_PIXEL_FORMAT_BYTE;
00111 }
00112 }
00113
00114 char const* vil_mit_image::file_format() const
00115 {
00116 return vil_mit_format_tag;
00117 }
00118
00119 vil_mit_image::vil_mit_image(vil_stream* is,
00120 unsigned int ni, unsigned int nj, unsigned int nplanes,
00121 vil_pixel_format format)
00122 : is_(is), ni_(ni), nj_(nj), components_(nplanes), format_(format)
00123 {
00124 is_->ref();
00125 write_header();
00126 }
00127
00128 vil_mit_image::~vil_mit_image()
00129 {
00130 is_->unref();
00131 }
00132
00133 bool vil_mit_image::get_property(char const * , void * ) const
00134 {
00135
00136 return false;
00137 }
00138
00139 bool vil_mit_image::read_header()
00140 {
00141 is_->seek(0L);
00142
00143 type_ = vil_stream_read_little_endian_uint_16(is_);
00144 unsigned int bpp = vil_stream_read_little_endian_uint_16(is_);
00145 ni_ = vil_stream_read_little_endian_uint_16(is_);
00146 nj_ = vil_stream_read_little_endian_uint_16(is_);
00147
00148 if (type_ == MIT_UNSIGNED) {
00149 components_ = 1;
00150 format_ = bpp==8 ? VIL_PIXEL_FORMAT_BYTE :
00151 bpp==16 ? VIL_PIXEL_FORMAT_UINT_16 :
00152 bpp==32 ? VIL_PIXEL_FORMAT_UINT_32 :
00153 bpp==1 ? VIL_PIXEL_FORMAT_BOOL :
00154 VIL_PIXEL_FORMAT_UNKNOWN;
00155 }
00156 else if (type_ == MIT_SIGNED) {
00157 components_ = 1;
00158 format_ = bpp==8 ? VIL_PIXEL_FORMAT_SBYTE :
00159 bpp==16 ? VIL_PIXEL_FORMAT_INT_16 :
00160 bpp==32 ? VIL_PIXEL_FORMAT_INT_32 :
00161 VIL_PIXEL_FORMAT_UNKNOWN;
00162 }
00163 else if (type_ == MIT_RGB) {
00164 components_ = 3;
00165 format_ = bpp==8 ? VIL_PIXEL_FORMAT_BYTE :
00166 bpp==16 ? VIL_PIXEL_FORMAT_UINT_16 :
00167 bpp==32 ? VIL_PIXEL_FORMAT_UINT_32 :
00168 VIL_PIXEL_FORMAT_UNKNOWN;
00169 }
00170 else if (type_ == MIT_FLOAT) {
00171 components_ = 1;
00172 format_ = bpp==32 ? VIL_PIXEL_FORMAT_FLOAT :
00173 bpp==64 ? VIL_PIXEL_FORMAT_DOUBLE :
00174 VIL_PIXEL_FORMAT_UNKNOWN;
00175 }
00176 else
00177 return false;
00178
00179 return format_ != VIL_PIXEL_FORMAT_UNKNOWN;
00180 }
00181
00182 bool vil_mit_image::write_header()
00183 {
00184 is_->seek(0L);
00185
00186 if (format_ == VIL_PIXEL_FORMAT_UINT_32 ||
00187 format_ == VIL_PIXEL_FORMAT_UINT_16 ||
00188 format_ == VIL_PIXEL_FORMAT_BYTE ||
00189 format_ == VIL_PIXEL_FORMAT_BOOL)
00190 {
00191 if (components_ == 3) type_ = MIT_RGB;
00192 else if (components_ == 1) type_ = MIT_UNSIGNED;
00193 else vcl_cerr << __FILE__ " : Can only write RGB or grayscale MIT images\n"
00194 << " (format="<<format_<<", #components="<<components_<<")\n";
00195 }
00196 else if (format_ == VIL_PIXEL_FORMAT_INT_32 ||
00197 format_ == VIL_PIXEL_FORMAT_INT_16 ||
00198 format_ == VIL_PIXEL_FORMAT_SBYTE)
00199 {
00200 if (components_ == 1) type_ = MIT_SIGNED;
00201 else vcl_cerr << __FILE__ " : Can only write RGB or grayscale MIT images\n"
00202 << " (format="<<format_<<", #components="<<components_<<")\n";
00203 }
00204 else if (format_ == VIL_PIXEL_FORMAT_RGB_UINT_32 ||
00205 format_ == VIL_PIXEL_FORMAT_RGB_INT_32 ||
00206 format_ == VIL_PIXEL_FORMAT_RGB_UINT_16 ||
00207 format_ == VIL_PIXEL_FORMAT_RGB_INT_16 ||
00208 format_ == VIL_PIXEL_FORMAT_RGB_BYTE ||
00209 format_ == VIL_PIXEL_FORMAT_RGB_SBYTE)
00210 {
00211 if (components_ == 1) type_ = MIT_RGB;
00212 else vcl_cerr << __FILE__ " : Can only write RGB or grayscale MIT images\n"
00213 << " (format="<<format_<<", #components="<<components_<<")\n";
00214 }
00215 else if (format_ == VIL_PIXEL_FORMAT_RGB_FLOAT ||
00216 format_ == VIL_PIXEL_FORMAT_RGB_DOUBLE)
00217 {
00218 if (components_ == 1) type_ = MIT_FLOAT;
00219 else vcl_cerr << __FILE__ " : Can only write grayscale float-pixel MIT images\n"
00220 << " (format="<<format_<<", #components="<<components_<<")\n";
00221 }
00222 else
00223 vcl_cerr << __FILE__ " : Can only write RGB or grayscale MIT images\n"
00224 << " (format="<<format_<<", #components="<<components_<<")\n";
00225
00226 vil_stream_write_little_endian_uint_16(is_, type_);
00227 unsigned int bpp = 8 * bytes_per_pixel();
00228 if (format_ == VIL_PIXEL_FORMAT_BOOL) bpp = 1;
00229 vil_stream_write_little_endian_uint_16(is_, bpp);
00230 vil_stream_write_little_endian_uint_16(is_, ni_);
00231 vil_stream_write_little_endian_uint_16(is_, nj_);
00232 return true;
00233 }
00234
00235 static inline void swap(void* p,int length)
00236 {
00237 char* t = (char*)p;
00238 #ifdef DEBUG
00239 if (length == sizeof(vxl_uint_32) && *(vxl_uint_32*)p != 0) {
00240 vcl_cerr << "Swapping " << *(vxl_uint_32*)p;
00241 if (length == sizeof(float)) vcl_cerr << " (or " << *(float*)p << ')';
00242 }
00243 #endif
00244 for (int j=0;2*j<length;++j) { char c = t[j]; t[j] = t[length-j-1]; t[length-j-1] = c; }
00245 #ifdef DEBUG
00246 if (length == sizeof(vxl_uint_32) && *(vxl_uint_32*)p != 0) {
00247 vcl_cerr << " to " << *(vxl_uint_32*)p;
00248 if (length == sizeof(float)) vcl_cerr << " (or " << *(float*)p << ')';
00249 vcl_cerr << '\n';
00250 }
00251 #endif
00252 }
00253
00254 vil_image_view_base_sptr vil_mit_image::get_copy_view(unsigned int x0, unsigned int xs,
00255 unsigned int y0, unsigned int ys) const
00256 {
00257 assert(x0+xs<=ni_);
00258 assert(y0+ys<=nj_);
00259 unsigned int pix_size = 8*bytes_per_pixel();
00260 if (format_==VIL_PIXEL_FORMAT_BOOL) pix_size = 1;
00261 if (format_==VIL_PIXEL_FORMAT_BOOL && x0%8 != 0)
00262 vcl_cerr << "vil_mit_image::get_copy_view(): Warning: x0 should be a multiple of 8 for this type of image\n";
00263 pix_size *= components_;
00264
00265 vxl_uint_32 rowsize = (pix_size*xs+7)/8;
00266 vil_memory_chunk_sptr buf = new vil_memory_chunk(rowsize*ys,format_);
00267 vxl_byte* ib = reinterpret_cast<vxl_byte*>(buf->data());
00268 for (unsigned int y = y0; y < y0+ys; ++y)
00269 {
00270 is_->seek(8L + y*((ni_*pix_size+7)/8) + x0*pix_size/8);
00271 is_->read(ib, rowsize);
00272 ib += rowsize;
00273 }
00274 if (VXL_BIG_ENDIAN && bytes_per_pixel() > 1) {
00275 ib = reinterpret_cast<vxl_byte*>(buf->data());
00276 for (unsigned int i=0;i<xs*ys*components_;++i)
00277 swap(ib+i*bytes_per_pixel(),bytes_per_pixel());
00278 }
00279
00280 #define ARGS(T) buf, reinterpret_cast<T*>(buf->data()), xs,ys,components_, components_,xs*components_,1
00281 if (format_ == VIL_PIXEL_FORMAT_BOOL) return new vil_image_view<bool> (ARGS(bool));
00282 else if (format_ == VIL_PIXEL_FORMAT_BYTE) return new vil_image_view<vxl_byte> (ARGS(vxl_byte));
00283 else if (format_ == VIL_PIXEL_FORMAT_SBYTE) return new vil_image_view<vxl_sbyte> (ARGS(vxl_sbyte));
00284 else if (format_ == VIL_PIXEL_FORMAT_UINT_16) return new vil_image_view<vxl_uint_16>(ARGS(vxl_uint_16));
00285 else if (format_ == VIL_PIXEL_FORMAT_INT_16) return new vil_image_view<vxl_int_16> (ARGS(vxl_int_16));
00286 else if (format_ == VIL_PIXEL_FORMAT_UINT_32) return new vil_image_view<vxl_uint_32>(ARGS(vxl_uint_32));
00287 else if (format_ == VIL_PIXEL_FORMAT_INT_32) return new vil_image_view<vxl_int_32> (ARGS(vxl_int_32));
00288 else if (format_ == VIL_PIXEL_FORMAT_FLOAT) return new vil_image_view<float> (ARGS(float));
00289 else if (format_ == VIL_PIXEL_FORMAT_DOUBLE) return new vil_image_view<double> (ARGS(double));
00290 else return 0;
00291 #undef ARGS
00292 }
00293
00294 bool vil_mit_image::put_view(vil_image_view_base const& buf, unsigned int x0, unsigned int y0)
00295 {
00296 assert(buf.pixel_format() == format_);
00297 if (!view_fits(buf, x0, y0) || buf.nplanes() != components_)
00298 {
00299 vil_exception_warning(vil_exception_out_of_bounds("vil_mit_image::put_view"));
00300 return false;
00301 }
00302 unsigned int ni = buf.ni();
00303 unsigned int nj = buf.nj();
00304 #ifdef DEBUG
00305 vcl_cerr<<"vil_mit_image::put_view() : buf="
00306 <<ni<<'x'<<nj<<'x'<< buf.nplanes()<<'p'
00307 <<" at ("<<x0<<','<<y0<<")\n";
00308 #endif
00309 vil_image_view<vxl_byte> const& ibuf = reinterpret_cast<vil_image_view<vxl_byte> const&>(buf);
00310 bool buf_is_planar = false;
00311 if (ibuf.istep() == int(components_) && ibuf.jstep() == int(components_*ni) &&
00312 (ibuf.planestep() == 1 || components_ == 1))
00313 buf_is_planar = false;
00314 else if (ibuf.istep() == 1 && ibuf.jstep() == int(ni) &&
00315 (ibuf.planestep() == int(ni*nj) || components_ == 1))
00316 buf_is_planar = true;
00317 else
00318 {
00319 vcl_cerr << "ERROR: " << __FILE__ << ":\n"
00320 << " view does not fit: istep="<<ibuf.istep()
00321 << ", jstep="<<ibuf.jstep()
00322 << ", planestep="<<ibuf.planestep()
00323 << " instead of "<<components_<<','<<components_*ni<<','<<1
00324 << " or 1,"<<ni<<','<<ni*nj<<'\n';
00325 return buf_is_planar;
00326 }
00327 const vxl_byte* ob = ibuf.top_left_ptr();
00328 unsigned int pix_size = 8*bytes_per_pixel();
00329 if (format_==VIL_PIXEL_FORMAT_BOOL) pix_size = 1;
00330 if (format_==VIL_PIXEL_FORMAT_BOOL && x0%8 != 0)
00331 vcl_cerr << "vil_mit_image::put_view(): Warning: x0 should be a multiple of 8 for this type of image\n";
00332 pix_size *= components_;
00333
00334 vxl_uint_32 rowsize = (pix_size*ni+7)/8;
00335
00336 if (VXL_LITTLE_ENDIAN || bytes_per_pixel() == 1)
00337 {
00338 if (buf_is_planar && components_ > 1)
00339 {
00340 vil_streampos sz = (pix_size/components_+7)/8;
00341 for (unsigned int y = y0; y < y0+nj; ++y)
00342 for (unsigned int x = x0; x < x0+ni; ++x)
00343 {
00344 is_->seek(8L + y*((ni_*pix_size+7)/8) + x*pix_size/8);
00345 for (unsigned int p=0; p<components_; ++p)
00346 if (sz != is_->write(ob+p*ni*nj*sz, sz))
00347 vcl_cerr << "WARNING: " << __FILE__ << ":\n"
00348 << " could not write "<<sz<<" bytes to stream; y,x="<<y<<','<<x<<'\n';
00349 #ifdef DEBUG
00350 else
00351 vcl_cerr << "written "<<sz<<" bytes to stream; y,x="<<y<<','<<x<<'\n';
00352 #endif
00353 ob += sz;
00354 }
00355 }
00356 else
00357 for (unsigned int y = y0; y < y0+nj; ++y)
00358 {
00359 is_->seek(8L + y*((ni_*pix_size+7)/8) + x0*pix_size/8);
00360 if ((vil_streampos)rowsize != is_->write(ob, rowsize))
00361 vcl_cerr << "WARNING: " << __FILE__ << ":\n"
00362 << " could not write "<<rowsize<<" bytes to stream; y="<<y<<'\n';
00363 #ifdef DEBUG
00364 else
00365 vcl_cerr << "written "<<rowsize<<" bytes to stream; y="<<y<<'\n';
00366 #endif
00367 ob += rowsize;
00368 }
00369 }
00370 else
00371 {
00372 if (buf_is_planar && components_ > 1)
00373 {
00374 unsigned int sz = bytes_per_pixel();
00375 vxl_byte* tempbuf = new vxl_byte[components_*sz];
00376 for (unsigned int y = y0; y < y0+nj; ++y)
00377 for (unsigned int x = x0; x < x0+ni; ++x)
00378 {
00379 for (unsigned int p=0; p<components_; ++p) {
00380 vcl_memcpy(tempbuf+p*sz, ob+p*ni*nj, sz);
00381 swap(tempbuf+p*sz,sz);
00382 }
00383 is_->seek(8L + pix_size*(y*ni_+x)/8);
00384 if (vil_streampos(components_*sz) != is_->write(tempbuf, components_*sz))
00385 vcl_cerr << "WARNING: " << __FILE__ << ":\n"
00386 << " could not write "<<components_*sz<<" bytes to stream; y,x="<<y<<','<<x<<'\n';
00387 #ifdef DEBUG
00388 else
00389 vcl_cerr << "written "<<components_*sz<<" bytes to stream; y,x="<<y<<','<<x<<'\n';
00390 #endif
00391 ob += sz;
00392 }
00393 delete[] tempbuf;
00394 }
00395 else
00396 {
00397 vxl_byte* tempbuf = new vxl_byte[rowsize];
00398 for (unsigned int y = y0; y < y0+nj; ++y)
00399 {
00400 vcl_memcpy(tempbuf, ob, rowsize);
00401 for (vxl_uint_32 i=0; i<rowsize; i+=bytes_per_pixel())
00402 swap(tempbuf+i,bytes_per_pixel());
00403 is_->seek(8L + bytes_per_pixel()*(y*ni_+x0));
00404 if ((vil_streampos)rowsize != is_->write(tempbuf, rowsize))
00405 vcl_cerr << "WARNING: " << __FILE__ << ":\n"
00406 << " could not write "<<rowsize<<" bytes to stream; y="<<y<<'\n';
00407 #ifdef DEBUG
00408 else
00409 vcl_cerr << "written "<<rowsize<<" bytes to stream; y="<<y<<'\n';
00410 #endif
00411 ob += rowsize;
00412 }
00413 delete[] tempbuf;
00414 }
00415 }
00416 return true;
00417 }