00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008 #include "vil1_ras.h"
00009
00010 #include <vcl_cassert.h>
00011 #include <vcl_iostream.h>
00012 #include <vcl_cstring.h>
00013
00014 #include <vil1/vil1_stream.h>
00015 #include <vil1/vil1_image_impl.h>
00016 #include <vil1/vil1_image.h>
00017 #include <vil1/vil1_property.h>
00018
00019 #include <vxl_config.h>
00020
00021 char const* vil1_ras_format_tag = "ras";
00022
00023 namespace {
00024 #if VXL_LITTLE_ENDIAN
00025 inline void swap_endian( vxl_uint_32& word )
00026 {
00027 vxl_uint_8* bytes = (vxl_uint_8*)&word;
00028 vxl_uint_8 t = bytes[0];
00029 bytes[0] = bytes[3];
00030 bytes[3] = t;
00031 t = bytes[1];
00032 bytes[1] = bytes[2];
00033 bytes[2] = t;
00034 }
00035 #else // VXL_BIG_ENDIAN: do nothing
00036 inline void swap_endian( vxl_uint_32& ) {}
00037 #endif
00038
00039
00040 bool read_uint_32( vil1_stream* vs, vxl_uint_32& word )
00041 {
00042 if ( vs->read( &word, 4 ) < 4 )
00043 return false;
00044 swap_endian( word );
00045 return true;
00046 }
00047
00048
00049 bool write_uint_32( vil1_stream* vs, vxl_uint_32 word )
00050 {
00051 swap_endian( word );
00052 return vs->write( &word, 4 ) == 4;
00053 }
00054
00055
00056
00057
00058 vxl_uint_32 compute_length( vxl_uint_32 w, vxl_uint_32 h, vxl_uint_32 d )
00059 {
00060 w *= (d/8);
00061 w += (w%2);
00062 return h*w;
00063 }
00064
00065
00066
00067 const vxl_uint_8 RAS_MAGIC[] = { 0x59, 0xA6, 0x6A, 0x95 };
00068 const vxl_uint_32 RT_OLD = 0;
00069 const vxl_uint_32 RT_STANDARD = 1;
00070 const vxl_uint_32 RT_BYTE_ENCODED = 2;
00071 const vxl_uint_32 RT_FORMAT_RGB = 3;
00072 const vxl_uint_32 RMT_NONE = 0;
00073 const vxl_uint_32 RMT_EQUAL_RGB = 1;
00074 }
00075
00076
00077 vil1_image_impl* vil1_ras_file_format::make_input_image(vil1_stream* vs)
00078 {
00079
00080 vxl_uint_8 buf[4] = { 0, 0, 0, 0 };
00081 vs->read(buf, 4);
00082 if ( ! ( buf[0] == RAS_MAGIC[0] && buf[1] == RAS_MAGIC[1] &&
00083 buf[2] == RAS_MAGIC[2] && buf[3] == RAS_MAGIC[3] ) )
00084 return 0;
00085
00086 return new vil1_ras_generic_image(vs);
00087 }
00088
00089 vil1_image_impl* vil1_ras_file_format::make_output_image(vil1_stream* vs, int planes,
00090 int width,
00091 int height,
00092 int components,
00093 int bits_per_component,
00094 vil1_component_format format)
00095 {
00096 return new vil1_ras_generic_image(vs, planes, width, height, components, bits_per_component, format);
00097 }
00098
00099 char const* vil1_ras_file_format::tag() const
00100 {
00101 return vil1_ras_format_tag;
00102 }
00103
00104
00105
00106 vil1_ras_generic_image::vil1_ras_generic_image(vil1_stream* vs):
00107 vs_(vs)
00108 {
00109 vs_->ref();
00110 read_header();
00111 }
00112
00113 bool vil1_ras_generic_image::get_property(char const *tag, void *prop) const
00114 {
00115 if (0==vcl_strcmp(tag, vil1_property_top_row_first))
00116 return prop ? (*(bool*)prop) = true : true;
00117
00118 if (0==vcl_strcmp(tag, vil1_property_left_first))
00119 return prop ? (*(bool*)prop) = true : true;
00120
00121
00122
00123 if (0==vcl_strcmp(tag, vil1_property_component_order_is_BGR)) {
00124 if ( prop )
00125 (*(bool*)prop) = ( map_type_ == RMT_NONE && type_ != RT_FORMAT_RGB );
00126 return true;
00127 }
00128
00129 return false;
00130 }
00131
00132 char const* vil1_ras_generic_image::file_format() const
00133 {
00134 return vil1_ras_format_tag;
00135 }
00136
00137 vil1_ras_generic_image::vil1_ras_generic_image(vil1_stream* vs, int planes,
00138 int width,
00139 int height,
00140 int components,
00141 int bits_per_component,
00142 vil1_component_format )
00143 : vs_(vs)
00144 {
00145 vs_->ref();
00146 width_ = width;
00147 height_ = height;
00148
00149 if ( planes != 1 ) {
00150 vcl_cerr << __FILE__ << ": can only handle 1 plane\n";
00151 return;
00152 }
00153 if ( components != 3 && components != 1 ) {
00154 vcl_cerr << __FILE__ << ": can't handle " << components << " components\n";
00155 return;
00156 }
00157 if ( bits_per_component != 8 ) {
00158 vcl_cerr << __FILE__ << ": can't handle " << bits_per_component << " bits per component\n";
00159 return;
00160 }
00161
00162 components_ = components;
00163 bits_per_component_ = bits_per_component;
00164 depth_ = components_ * bits_per_component_;
00165
00166 if (components_ == 3) {
00167 type_ = RT_FORMAT_RGB;
00168 } else {
00169 type_ = RT_STANDARD;
00170 }
00171 map_type_ = RMT_NONE;
00172 map_length_ = 0;
00173 length_ = compute_length( width_, height_, depth_ );
00174 col_map_ = 0;
00175
00176 write_header();
00177 }
00178
00179 vil1_ras_generic_image::~vil1_ras_generic_image()
00180 {
00181 delete[] col_map_;
00182 vs_->unref();
00183 }
00184
00185
00186
00187 bool vil1_ras_generic_image::read_header()
00188 {
00189
00190 vs_->seek(0);
00191
00192 vxl_uint_8 buf[4];
00193 if (vs_->read(buf, 4) < 4)
00194 return false;
00195 if (! ( buf[0] == RAS_MAGIC[0] && buf[1] == RAS_MAGIC[1] &&
00196 buf[2] == RAS_MAGIC[2] && buf[3] == RAS_MAGIC[3] ) )
00197 return false;
00198
00199 if (!( read_uint_32( vs_, width_ ) &&
00200 read_uint_32( vs_, height_ ) &&
00201 read_uint_32( vs_, depth_ ) &&
00202 read_uint_32( vs_, length_ ) &&
00203 read_uint_32( vs_, type_ ) &&
00204 read_uint_32( vs_, map_type_ ) &&
00205 read_uint_32( vs_, map_length_ ) ) )
00206 return false;
00207
00208
00209
00210 if (type_ != RT_OLD && type_ != RT_STANDARD &&
00211 type_ != RT_BYTE_ENCODED && type_ != RT_FORMAT_RGB ) {
00212 vcl_cerr << __FILE__ << ": unknown type " << type_ << vcl_endl;
00213 return false;
00214 }
00215 if ( map_type_ != RMT_NONE && map_type_ != RMT_EQUAL_RGB ) {
00216 vcl_cerr << __FILE__ << ": unknown map type " << map_type_ << vcl_endl;
00217 return false;
00218 }
00219 if ( map_type_ == RMT_NONE && map_length_ != 0 ) {
00220 vcl_cerr << __FILE__ << ": No colour map according to header, but there is a map!\n";
00221 return false;
00222 }
00223
00224 if ( depth_ != 8 && depth_ != 24 ) {
00225 vcl_cerr << __FILE__ << ": depth " << depth_ << " not implemented\n";
00226 return false;
00227 }
00228
00229
00230 if ( type_ == RT_OLD ) {
00231 length_ = compute_length( width_, height_, depth_ );
00232 }
00233 if ( length_ == 0 ) {
00234 vcl_cerr << __FILE__ << ": header says image has length zero\n";
00235 return false;
00236 }
00237 if ( type_ != RT_BYTE_ENCODED && length_ != compute_length( width_, height_, depth_ ) ) {
00238 vcl_cerr << __FILE__ << ": length " << length_ << " does not match wxhxd = "
00239 << compute_length( width_, height_, depth_ ) << vcl_endl;
00240 return false;
00241 }
00242
00243 if ( map_length_ ) {
00244 assert( map_length_ % 3 == 0 );
00245 col_map_ = new vxl_uint_8[ map_length_ ];
00246 vs_->read( col_map_, (vil1_streampos)map_length_ );
00247 } else {
00248 col_map_ = 0;
00249 }
00250
00251 start_of_data_ = vs_->tell();
00252
00253 assert( depth_ == 8 || depth_ == 24 );
00254
00255 if ( map_type_ != RMT_NONE || depth_ == 24 ) {
00256 components_ = 3;
00257 } else {
00258 components_ = 1;
00259 }
00260 bits_per_component_ = 8;
00261
00262 return true;
00263 }
00264
00265 bool vil1_ras_generic_image::write_header()
00266 {
00267 vs_->seek(0);
00268
00269 vs_->write( RAS_MAGIC, 4 );
00270
00271 write_uint_32( vs_, width_ );
00272 write_uint_32( vs_, height_ );
00273 write_uint_32( vs_, depth_ );
00274 write_uint_32( vs_, length_ );
00275 write_uint_32( vs_, type_ );
00276 write_uint_32( vs_, map_type_ );
00277 write_uint_32( vs_, map_length_ );
00278
00279 assert( map_length_ == 0 );
00280
00281 start_of_data_ = vs_->tell();
00282
00283 return true;
00284 }
00285
00286 bool vil1_ras_generic_image::get_section(void* buf, int x0, int y0, int xs, int ys) const
00287 {
00288 if ( type_ == RT_BYTE_ENCODED )
00289 return false;
00290
00291 int file_bytes_per_pixel = (depth_+7)/8;
00292 int buff_bytes_per_pixel = components_ * ( (bits_per_component_+7)/8 );
00293 int file_byte_width = width_ * file_bytes_per_pixel;
00294 file_byte_width += ( file_byte_width % 2 );
00295 int file_byte_start = start_of_data_ + y0 * file_byte_width + x0 * file_bytes_per_pixel;
00296 int buff_byte_width = xs * buff_bytes_per_pixel;
00297
00298 vxl_uint_8* ib = (vxl_uint_8*) buf;
00299
00300 if ( !col_map_ ) {
00301
00302
00303 for (int y = 0; y < ys; ++y) {
00304 vs_->seek(file_byte_start + y * file_byte_width);
00305 vs_->read(ib + y * buff_byte_width, buff_byte_width);
00306 }
00307
00308 } else {
00309 assert( file_bytes_per_pixel == 1 && buff_bytes_per_pixel == 3 );
00310 int col_len = map_length_ / 3;
00311
00312 vxl_uint_8* line = new vxl_uint_8[ xs ];
00313 for (int y = 0; y < ys; ++y) {
00314 vs_->seek( file_byte_start + y * file_byte_width );
00315 vs_->read( line, xs );
00316 vxl_uint_8* in_p = line;
00317 vxl_uint_8* out_p = ib + y * buff_byte_width;
00318 for ( int i=0; i < xs; ++i ) {
00319 assert( *in_p < col_len );
00320 *(out_p++) = col_map_[ *in_p ];
00321 *(out_p++) = col_map_[ *in_p + col_len ];
00322 *(out_p++) = col_map_[ *in_p + 2*col_len ];
00323 ++in_p;
00324 }
00325 }
00326 delete[] line;
00327 }
00328
00329 return true;
00330 }
00331
00332 bool vil1_ras_generic_image::put_section(void const* buf, int x0, int y0, int xs, int ys)
00333 {
00334 if ( col_map_ ) {
00335 vcl_cerr << __FILE__ << ": writing to file with a colour map is not implemented\n";
00336 return false;
00337 }
00338 if ( type_ == RT_BYTE_ENCODED ) {
00339 vcl_cerr << __FILE__ << ": writing to a run-length encoded file is not implemented\n";
00340 return false;
00341 }
00342 if ( components_ == 3 && type_ != RT_FORMAT_RGB ) {
00343 vcl_cerr << __FILE__ << ": writing BGR format is not implemented\n";
00344 return false;
00345 }
00346
00347
00348
00349 int file_bytes_per_pixel = (depth_+7)/8;
00350 int buff_bytes_per_pixel = components_ * ( (bits_per_component_+7)/8 );
00351 int file_byte_width = width_ * file_bytes_per_pixel;
00352 file_byte_width += ( file_byte_width % 2 );
00353 int file_byte_start = start_of_data_ + y0 * file_byte_width + x0 * file_bytes_per_pixel;
00354 int buff_byte_width = xs * buff_bytes_per_pixel;
00355
00356 assert( file_bytes_per_pixel == buff_bytes_per_pixel );
00357 assert( file_byte_width >= buff_byte_width );
00358
00359
00360
00361 bool need_pad = ( file_byte_width == buff_byte_width+1 );
00362 vxl_uint_8 zero = 0;
00363
00364 vxl_uint_8 const* ob = (vxl_uint_8 const*) buf;
00365
00366 for (int y = 0; y < ys; ++y) {
00367 vs_->seek( file_byte_start + y * file_byte_width );
00368 vs_->write( ob + y * buff_byte_width, buff_byte_width );
00369 if ( need_pad )
00370 vs_->write( &zero, 1 );
00371 }
00372
00373 return true;
00374 }
00375
00376 vil1_image vil1_ras_generic_image::get_plane(unsigned int plane) const
00377 {
00378 assert(plane == 0);
00379 return const_cast<vil1_ras_generic_image*>(this);
00380 }