00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006 #include "vil1_viff.h"
00007 extern "C" {
00008 #include "vil1_viff_support.h"
00009 }
00010 #include <vcl_cassert.h>
00011
00012 char const* vil1_viff_format_tag = "viff";
00013
00014 #include <vcl_iostream.h>
00015 #include <vcl_cstring.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 inline void swap(void* p,int length)
00023 {
00024 char* t = (char*)p;
00025 #ifdef DEBUG
00026 if (length == sizeof(vxl_uint_32) && *(vxl_uint_32*)p != 0) {
00027 vcl_cerr << "Swapping " << *(vxl_uint_32*)p;
00028 if (length == sizeof(float))
00029 vcl_cerr << " (or " << *(float*)p << ')';
00030 }
00031 #endif
00032 for (int j=0;2*j<length;++j)
00033 {
00034 char c = t[j];
00035 t[j] = t[length-j-1];
00036 t[length-j-1] = c;
00037 }
00038 #ifdef DEBUG
00039 if (length == sizeof(vxl_uint_32) && *(vxl_uint_32*)p != 0) {
00040 vcl_cerr << " to " << *(vxl_uint_32*)p;
00041 if (length == sizeof(float))
00042 vcl_cerr << " (or " << *(float*)p << ')';
00043 vcl_cerr << '\n';
00044 }
00045 #endif
00046 }
00047
00048 vil1_image_impl* vil1_viff_file_format::make_input_image(vil1_stream* is)
00049 {
00050
00051 if (!is) return 0;
00052 is->seek(0L);
00053 vil1_viff_xvimage header;
00054 if (VIFF_HEADERSIZE != is->read((void*)(&header),VIFF_HEADERSIZE))
00055 return 0;
00056
00057 if (header.identifier != (char)XV_FILE_MAGIC_NUM ||
00058 header.file_type != (char)XV_FILE_TYPE_XVIFF)
00059 return 0;
00060
00061 vxl_uint_32 dst = header.data_storage_type;
00062 if ((dst & 0xff) == 0)
00063 swap(&dst,sizeof(dst));
00064 switch (dst)
00065 {
00066 case VFF_TYP_BIT:
00067 case VFF_TYP_1_BYTE:
00068 case VFF_TYP_2_BYTE:
00069 case VFF_TYP_4_BYTE:
00070 case VFF_TYP_FLOAT:
00071 case VFF_TYP_DOUBLE:
00072 case VFF_TYP_COMPLEX:
00073 case VFF_TYP_DCOMPLEX:
00074 return new vil1_viff_generic_image(is);
00075 default:
00076 vcl_cout << "vil1_viff: non supported data type: VFF_TYP "
00077 << header.data_storage_type << vcl_endl;
00078 return 0;
00079 }
00080 }
00081
00082 vil1_image_impl* vil1_viff_file_format::make_output_image(vil1_stream* is, int planes,
00083 int width,
00084 int height,
00085 int components,
00086 int bits_per_component,
00087 vil1_component_format format)
00088 {
00089 return new vil1_viff_generic_image(is, planes, width, height, components, bits_per_component, format);
00090 }
00091
00092 char const* vil1_viff_file_format::tag() const
00093 {
00094 return vil1_viff_format_tag;
00095 }
00096
00097
00098
00099 vil1_viff_generic_image::vil1_viff_generic_image(vil1_stream* is)
00100 : is_(is)
00101 {
00102 is_->ref();
00103 if (!read_header())
00104 {
00105 vcl_cerr << "vil1_viff: cannot read file header; creating dummy 0x0 image\n";
00106 start_of_data_ = VIFF_HEADERSIZE; endian_consistent_ = true;
00107 width_ = height_ = 0; planes_ = 1; maxval_ = 255;
00108 bits_per_component_ = 8; format_ = VIL1_COMPONENT_FORMAT_UNSIGNED_INT;
00109 }
00110 }
00111
00112 bool vil1_viff_generic_image::get_property(char const *tag, void *prop) const
00113 {
00114 if (0==vcl_strcmp(tag, vil1_property_top_row_first))
00115 return prop ? (*(bool*)prop) = true : true;
00116
00117 if (0==vcl_strcmp(tag, vil1_property_left_first))
00118 return prop ? (*(bool*)prop) = true : true;
00119
00120 return false;
00121 }
00122
00123 char const* vil1_viff_generic_image::file_format() const
00124 {
00125 return vil1_viff_format_tag;
00126 }
00127
00128 vil1_viff_generic_image::vil1_viff_generic_image(vil1_stream* is, int planes,
00129 int width,
00130 int height,
00131 int ,
00132 int bits_per_component,
00133 vil1_component_format format)
00134 : is_(is), width_(width), height_(height),
00135 maxval_(255), planes_(planes), start_of_data_(VIFF_HEADERSIZE),
00136 bits_per_component_(bits_per_component),
00137 format_(format), endian_consistent_(true)
00138 {
00139 is_->ref();
00140 write_header();
00141 }
00142
00143 vil1_viff_generic_image::~vil1_viff_generic_image()
00144 {
00145 is_->unref();
00146 }
00147
00148 bool vil1_viff_generic_image::read_header()
00149 {
00150
00151 is_->seek(0L);
00152 start_of_data_ = VIFF_HEADERSIZE;
00153
00154
00155 if (VIFF_HEADERSIZE != is_->read((void*)(&header_),VIFF_HEADERSIZE))
00156 return false;
00157
00158 if (header_.identifier != (char)XV_FILE_MAGIC_NUM ||
00159 header_.file_type != (char)XV_FILE_TYPE_XVIFF)
00160 return false;
00161
00162 check_endian();
00163
00164
00165 maxval_ = 0;
00166
00167 vxl_uint_32 rs = header_.row_size;
00168 vxl_uint_32 cs = header_.col_size;
00169 vxl_uint_32 dst = header_.data_storage_type;
00170 vxl_uint_32 ndb = header_.num_data_bands;
00171
00172 vxl_uint_32 ispare1 = header_.ispare1;
00173 vxl_uint_32 ispare2 = header_.ispare2;
00174 float fspare1 = header_.fspare1;
00175 float fspare2 = header_.fspare2;
00176
00177 if (!endian_consistent_)
00178 {
00179 swap(&rs,sizeof(rs));
00180 swap(&cs,sizeof(cs));
00181 swap(&dst,sizeof(dst));
00182 swap(&ndb,sizeof(ndb));
00183 swap(&ispare1,sizeof(ispare1));
00184 swap(&ispare2,sizeof(ispare2));
00185 swap(&fspare1,sizeof(fspare1));
00186 swap(&fspare2,sizeof(fspare2));
00187 }
00188
00189 width_ = rs;
00190 height_ = cs;
00191 planes_ = (int)ndb;
00192
00193
00194 switch (dst)
00195 {
00196 case VFF_TYP_BIT:
00197 format_ = VIL1_COMPONENT_FORMAT_UNSIGNED_INT;
00198 bits_per_component_ = 1;
00199 break;
00200 case VFF_TYP_1_BYTE:
00201 format_ = VIL1_COMPONENT_FORMAT_UNSIGNED_INT;
00202 bits_per_component_ = 8;
00203 break;
00204 case VFF_TYP_2_BYTE:
00205 format_ = VIL1_COMPONENT_FORMAT_UNSIGNED_INT;
00206 bits_per_component_ = 16;
00207 break;
00208 case VFF_TYP_4_BYTE:
00209 format_ = VIL1_COMPONENT_FORMAT_UNSIGNED_INT;
00210 bits_per_component_ = 32;
00211 break;
00212 case VFF_TYP_FLOAT:
00213 format_ = VIL1_COMPONENT_FORMAT_IEEE_FLOAT;
00214 bits_per_component_ = 32;
00215 break;
00216 case VFF_TYP_DOUBLE:
00217 format_ = VIL1_COMPONENT_FORMAT_IEEE_FLOAT;
00218 bits_per_component_ = 64;
00219 break;
00220 case VFF_TYP_COMPLEX:
00221 format_ = VIL1_COMPONENT_FORMAT_COMPLEX;
00222 bits_per_component_ = 64;
00223 break;
00224 case VFF_TYP_DCOMPLEX:
00225 format_ = VIL1_COMPONENT_FORMAT_COMPLEX;
00226 bits_per_component_ = 128;
00227 break;
00228 default:
00229 vcl_cout << "vil1_viff: non supported data type: VFF_TYP "
00230 << header_.data_storage_type << vcl_endl;
00231 format_ = VIL1_COMPONENT_FORMAT_UNKNOWN;
00232 return false;
00233 }
00234
00235 return true;
00236 }
00237
00238 bool vil1_viff_generic_image::write_header()
00239 {
00240 is_->seek(0L);
00241 int type;
00242 if (bits_per_component_ > 1)
00243 bits_per_component_ = 8*((bits_per_component_+7)/8);
00244
00245 if (component_format()==VIL1_COMPONENT_FORMAT_SIGNED_INT ||
00246 component_format()==VIL1_COMPONENT_FORMAT_UNSIGNED_INT)
00247 {
00248 switch (bits_per_component_)
00249 {
00250 case 1: type=VFF_TYP_BIT; break;
00251 case 8: type=VFF_TYP_1_BYTE; break;
00252 case 16: type=VFF_TYP_2_BYTE; break;
00253 case 32: type=VFF_TYP_4_BYTE; break;
00254 default:
00255 vcl_cerr << "vil1_viff: non supported data type: " << bits_per_component_ << " bit pixels\n";
00256 return false;
00257 }
00258 }
00259 else if (component_format()==VIL1_COMPONENT_FORMAT_IEEE_FLOAT)
00260 {
00261 switch (bits_per_component_)
00262 {
00263 case 32: type=VFF_TYP_FLOAT; break;
00264 case 64: type=VFF_TYP_DOUBLE; break;
00265 default:
00266 vcl_cerr << "vil1_viff: non supported data type: " << bits_per_component_ << " bit float pixels\n";
00267 return false;
00268 }
00269 }
00270 else if (component_format()==VIL1_COMPONENT_FORMAT_COMPLEX)
00271 {
00272 switch (bits_per_component_)
00273 {
00274 case 64: type=VFF_TYP_COMPLEX; break;
00275 case 128: type=VFF_TYP_DCOMPLEX; break;
00276 default:
00277 vcl_cerr << "vil1_viff: non supported data type: " << bits_per_component_ << " bit complex pixels\n";
00278 return false;
00279 }
00280 }
00281 else
00282 {
00283 vcl_cout << "vil1_viff: non supported data type: " << (short)component_format() << vcl_endl;
00284 return false;
00285 }
00286
00287
00288 vil1_viff_xvimage *imagep = vil1_viff_createimage(height_, width_,
00289 type, 1, planes_,
00290 "vil1_viff image writer output",0,0,
00291 VFF_MS_NONE,VFF_MAPTYP_NONE,VFF_LOC_IMPLICIT,0);
00292
00293
00294 vcl_memcpy(&header_, imagep, sizeof(header_));
00295 start_of_data_ = sizeof(header_);
00296
00297
00298 vil1_viff_freeimage(imagep);
00299
00300 is_->write((void*)(&header_), start_of_data_);
00301 start_of_data_ = is_->tell();
00302 return true;
00303 }
00304
00305 bool vil1_viff_generic_image::get_section(void* buf, int x0, int y0, int xs, int ys) const
00306 {
00307 assert(x0>=0); assert(y0>=0);
00308 assert((x0+xs)<=width_);
00309 assert((y0+ys)<=height_);
00310 if (!buf) return false;
00311 unsigned char* ib = (unsigned char*) buf;
00312 if ((x0*bits_per_component_)%8 != 0)
00313 vcl_cerr << "vil1_viff_generic_image::get_section(): Warning: x0 should be a multiple of 8 for this type of image\n";
00314
00315 vxl_uint_32 rowsize = (bits_per_component_*xs+7)/8;
00316 vxl_uint_32 tbytes = rowsize*ys*planes_;
00317 for (int p = 0; p<planes_; ++p) {
00318 for (int y = y0; y < y0+ys; ++y) {
00319 is_->seek(start_of_data_ + p*height_*((width_*bits_per_component_+7)/8)
00320 + y*((width_*bits_per_component_+7)/8)
00321 + x0*bits_per_component_/8);
00322 is_->read(ib, rowsize);
00323 ib += rowsize;
00324 }
00325 }
00326 if (!endian_consistent_) {
00327 ib = (unsigned char*) buf;
00328 for (unsigned int i=0;i<tbytes;i+=bits_per_component_/8)
00329 swap(ib+i,bits_per_component_/8);
00330 }
00331
00332 return true;
00333 }
00334
00335 bool vil1_viff_generic_image::put_section(void const* buf, int x0, int y0, int xs, int ys)
00336 {
00337 assert(x0>=0); assert(y0>=0);
00338 assert((x0+xs)<=width_);
00339 assert((y0+ys)<=height_);
00340 if (!buf) return false;
00341 unsigned char const* ob = (unsigned char const*) buf;
00342 if ((x0*bits_per_component_)%8 != 0)
00343 vcl_cerr << "vil1_viff_generic_image::put_section(): Warning: x0 should be a multiple of 8 for this type of image\n";
00344
00345 vxl_uint_32 rowsize = (bits_per_component_*xs+7)/8;
00346 if (endian_consistent_)
00347 for (int p = 0; p<planes_; ++p)
00348 for (int y = y0; y < y0+ys; ++y) {
00349 is_->seek(start_of_data_ + p*height_*((width_*bits_per_component_+7)/8)
00350 + y*((width_*bits_per_component_+7)/8)
00351 + x0*bits_per_component_/8);
00352 is_->write(ob, rowsize);
00353 ob += rowsize;
00354 }
00355 else {
00356 unsigned char* tempbuf = new unsigned char[rowsize];
00357 for (int p = 0; p<planes_; ++p)
00358 for (int y = y0; y < y0+ys; ++y) {
00359 vcl_memcpy(tempbuf, ob, rowsize);
00360 for (unsigned int i=0; i<rowsize; i+=bits_per_component_/8)
00361 swap(tempbuf+i,bits_per_component_/8);
00362 is_->seek(start_of_data_ + p*width_*height_*bits_per_component_/8 + bits_per_component_*(y*width_+x0)/8);
00363 is_->write(tempbuf, rowsize);
00364 ob += rowsize;
00365 }
00366 delete[] tempbuf;
00367 }
00368 return true;
00369 }
00370
00371 bool vil1_viff_generic_image::check_endian()
00372 {
00373
00374
00375
00376
00377
00378 vxl_uint_32 dst = header_.data_storage_type;
00379
00380 endian_consistent_ = ((dst & 0xff) != 0);
00381 #ifdef DEBUG
00382 if (endian_consistent_)
00383 vcl_cerr << "Endian is Consistent\n";
00384 else
00385 vcl_cerr << "Endian is NOT Consistent\n";
00386 #endif
00387 return endian_consistent_;
00388 }
00389
00390 vil1_image vil1_viff_generic_image::get_plane(unsigned int plane) const
00391 {
00392 assert((int)plane < planes_);
00393 vcl_cerr << "FIXME: this should be an adapter that shifts to the plane asked for\n";
00394 return const_cast<vil1_viff_generic_image*>(this);
00395 }
00396
00397 bool vil1_viff_generic_image::get_section_rgb_byte(void* , int , int , int , int ) const
00398 {
00399 vcl_cerr << "FIXME: vil1_viff_generic_image::get_section_rgb_byte() not yet implemented\n";
00400 return false;
00401 }
00402
00403 bool vil1_viff_generic_image::get_section_float(void* buf, int x0, int y0, int width, int height) const
00404 {
00405 if (component_format()!=VIL1_COMPONENT_FORMAT_IEEE_FLOAT || bits_per_component_ != 32)
00406 return false;
00407 return get_section(buf,x0,y0,width,height);
00408 }
00409
00410 bool vil1_viff_generic_image::get_section_byte(void* buf, int x0, int y0, int width, int height) const
00411 {
00412 if (component_format()!=VIL1_COMPONENT_FORMAT_UNSIGNED_INT || bits_per_component_ != 8)
00413 return false;
00414 return get_section(buf,x0,y0,width,height);
00415 }
00416
00417 void vil1_viff_generic_image::set_ispare1(vxl_uint_32 ispare1)
00418 {
00419 header_.ispare1 = ispare1;
00420 int longsize = sizeof(vxl_uint_32);
00421 unsigned char* bytes = new unsigned char[longsize];
00422 vcl_memcpy(bytes,&ispare1,longsize);
00423 if (!endian_consistent_)
00424 swap(bytes,longsize);
00425
00426 is_->seek((int)((unsigned char*)&header_.ispare1 - (unsigned char*)&header_));
00427 is_->write(bytes, longsize);
00428 delete[] bytes;
00429 }
00430
00431 void vil1_viff_generic_image::set_ispare2(vxl_uint_32 ispare2)
00432 {
00433 header_.ispare2 = ispare2;
00434 int longsize = sizeof(vxl_uint_32);
00435 unsigned char* bytes = new unsigned char[longsize];
00436 vcl_memcpy(bytes,&ispare2,longsize);
00437 if (!endian_consistent_)
00438 swap(bytes,longsize);
00439
00440 is_->seek((int)((unsigned char*)&header_.ispare2 - (unsigned char*)&header_));
00441 is_->write(bytes, longsize);
00442 delete[] bytes;
00443 }
00444
00445 void vil1_viff_generic_image::set_fspare1(float fspare1)
00446 {
00447 header_.fspare1 = fspare1;
00448 int floatsize = sizeof(float);
00449 unsigned char* bytes = new unsigned char[floatsize];
00450 vcl_memcpy(bytes,&fspare1,floatsize);
00451 if (!endian_consistent_)
00452 swap(bytes,floatsize);
00453
00454 is_->seek((int)((unsigned char*)&header_.fspare1 - (unsigned char*)&header_));
00455 is_->write(bytes, floatsize);
00456
00457 delete[] bytes;
00458 }
00459
00460 void vil1_viff_generic_image::set_fspare2(float fspare2)
00461 {
00462 header_.fspare2 = fspare2;
00463 int floatsize = sizeof(float);
00464 unsigned char* bytes = new unsigned char[floatsize];
00465 vcl_memcpy(bytes,&fspare2,floatsize);
00466 if (!endian_consistent_)
00467 swap(bytes,floatsize);
00468
00469 is_->seek((int)((unsigned char*)&header_.fspare2 - (unsigned char*)&header_));
00470 is_->write(bytes, floatsize);
00471 delete[] bytes;
00472 }