00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006 #include "vil1_bmp.h"
00007
00008 #include <vcl_cassert.h>
00009 #include <vcl_iostream.h>
00010 #include <vcl_vector.h>
00011 #include <vcl_cstring.h>
00012 #include <vil1/vil1_stream.h>
00013 #include <vil1/vil1_property.h>
00014
00015 #define where (vcl_cerr << __FILE__ ":" << __LINE__ << " : ")
00016
00017
00018
00019 char const* vil1_bmp_format_tag = "bmp";
00020
00021 vil1_image_impl* vil1_bmp_file_format::make_input_image(vil1_stream* is)
00022 {
00023
00024 vil1_bmp_file_header hdr;
00025 is->seek(0L);
00026 hdr.read(is);
00027
00028 if ( hdr.signature_valid() )
00029 return new vil1_bmp_generic_image(is);
00030 else
00031 return 0;
00032 }
00033
00034 vil1_image_impl* vil1_bmp_file_format::make_output_image(vil1_stream* is, int planes,
00035 int width,
00036 int height,
00037 int components,
00038 int bits_per_component,
00039 vil1_component_format format)
00040 {
00041 return new vil1_bmp_generic_image(is, planes, width, height, components, bits_per_component, format);
00042 }
00043
00044 char const* vil1_bmp_file_format::tag() const
00045 {
00046 return vil1_bmp_format_tag;
00047 }
00048
00049
00050
00051 char const* vil1_bmp_generic_image::file_format() const
00052 {
00053 return vil1_bmp_format_tag;
00054 }
00055
00056 vil1_bmp_generic_image::vil1_bmp_generic_image(vil1_stream* is)
00057 : is_(is)
00058 , bit_map_start(-1L)
00059
00060
00061 {
00062 is_->ref();
00063 read_header();
00064 }
00065
00066 bool vil1_bmp_generic_image::get_property(char const *tag, void *prop) const
00067 {
00068 if (0==vcl_strcmp(tag, vil1_property_top_row_first))
00069 return prop ? (*(bool*)prop) = false, true : true;
00070
00071 if (0==vcl_strcmp(tag, vil1_property_left_first))
00072 return prop ? (*(bool*)prop) = true : true;
00073
00074 if (0==vcl_strcmp(tag, vil1_property_component_order_is_BGR))
00075 return prop ? (*(bool*)prop) = true : true;
00076
00077 return false;
00078 }
00079
00080 vil1_bmp_generic_image::vil1_bmp_generic_image(vil1_stream* is,
00081 int planes,
00082 int width,
00083 int height,
00084 int components,
00085 int bits_per_component,
00086 vil1_component_format )
00087 : is_(is)
00088 , bit_map_start(-1L)
00089 {
00090 is_->ref();
00091 assert(planes == 1);
00092
00093
00094 core_hdr.width = width;
00095 core_hdr.height = height;
00096 core_hdr.planes = planes;
00097
00098 assert(bits_per_component == 8 && (components == 1 || components == 3));
00099 core_hdr.bitsperpixel = bits_per_component * components;
00100
00101 write_header();
00102 }
00103
00104 vil1_bmp_generic_image::~vil1_bmp_generic_image()
00105 {
00106 #if 0
00107
00108 if (local_color_map_){
00109 delete [] local_color_map_[0];
00110 delete [] local_color_map_[1];
00111 delete [] local_color_map_[2];
00112 delete local_color_map_;
00113 }
00114
00115 if (freds_colormap) {
00116 delete [] freds_colormap[0];
00117 delete [] freds_colormap[1];
00118 delete [] freds_colormap[2];
00119 delete [] freds_colormap[3];
00120 delete [] freds_colormap;
00121 freds_colormap = 0;
00122 }
00123 #endif
00124
00125 is_->unref();
00126 }
00127
00128 bool vil1_bmp_generic_image::read_header()
00129 {
00130
00131 is_->seek(0L);
00132 file_hdr.read(is_);
00133 if ( ! file_hdr.signature_valid() ) {
00134 where << "File is not a valid BMP file\n";
00135 return false;
00136 }
00137 #ifdef DEBUG
00138 file_hdr.print(vcl_cerr);
00139 #endif
00140
00141
00142 core_hdr.read(is_);
00143 #ifdef DEBUG
00144 core_hdr.print(vcl_cerr);
00145 #endif
00146
00147
00148 if ( core_hdr.bitsperpixel != 8 && core_hdr.bitsperpixel != 24 ) {
00149 where << "BMP file has a non-supported pixel size of " << core_hdr.bitsperpixel << " bits\n";
00150 return false;
00151 }
00152
00153
00154
00155 if (core_hdr.header_size == vil1_bmp_core_header::disk_size) {
00156
00157 }
00158 else if (core_hdr.header_size == vil1_bmp_core_header::disk_size + vil1_bmp_info_header::disk_size) {
00159
00160 info_hdr.read(is_);
00161 #ifdef DEBUG
00162 info_hdr.print(vcl_cerr);
00163 #endif
00164 if (info_hdr.compression) {
00165 where << "cannot cope with compression at the moment\n";
00166 return false;
00167 }
00168 }
00169 else {
00170
00171 where << "dunno about header_size " << core_hdr.header_size << vcl_endl;
00172 return false;
00173 }
00174
00175
00176 is_->seek(file_hdr.bitmap_offset);
00177 #if 0
00178
00179 if (info_hdr.colormapsize ==0 && info_hdr.colorcount == 0) {
00180
00181 }
00182 else if (info_hdr.colormapsize == 256 && core_hdr.bitsperpixel == 8) {
00183
00184
00185
00186 typedef unsigned char uchar;
00187 freds_colormap = new uchar *[4];
00188 freds_colormap[0] = new uchar[256];
00189 freds_colormap[1] = new uchar[256];
00190 freds_colormap[2] = new uchar[256];
00191 freds_colormap[3] = new uchar[256];
00192 uchar bif[4];
00193 for (int i=0; i<256; ++i) {
00194 is_->read(bif, sizeof(bif));
00195 freds_colormap[0][i] = bif[0];
00196 freds_colormap[1][i] = bif[1];
00197 freds_colormap[2][i] = bif[2];
00198 freds_colormap[3][i] = bif[3];
00199 }
00200 }
00201 else {
00202
00203 assert(false);
00204 }
00205 #endif
00206
00207
00208 #if 0
00209
00210 int ccount=0;
00211
00212 if (header.biClrUsed != 0)
00213 ccount = header.biClrUsed;
00214 else if (header.biBitCount != 24)
00215 ccount = 1 << header.biBitCount;
00216 else {
00217 }
00218
00219 if (ccount != 0) {
00220 unsigned cmap_size;
00221 if (header.biSize == sizeof(xBITMAPCOREHEADER))
00222 cmap_size = ccount*3;
00223 else
00224 cmap_size = ccount*4;
00225
00226 vcl_vector<uchar> cmap(cmap_size, 0);
00227 if (is_->read(&cmap[0], 1024L) != 1024L) {
00228 vcl_cerr << "Error reading image palette\n";
00229 return false;
00230 }
00231
00232
00233
00234 int ncolors = ccount;
00235 if (ncolors != 0) {
00236 int **color_map = new int*[3];
00237 for (int i=0; i<3; ++i) {
00238 color_map[i] = new int[ncolors];
00239 for (int j=0; j<ncolors; j++)
00240 color_map[i][j] = (int) cmap[2-i+4*j];
00241 }
00242
00243
00244 local_color_map_=color_map;
00245 }
00246 }
00247
00248
00249 #endif
00250
00251
00252 bit_map_start = is_->tell();
00253 #ifdef DEBUG
00254 where << "bit_map_start = " << bit_map_start << vcl_endl;
00255 #endif
00256 assert(bit_map_start == (int)file_hdr.bitmap_offset);
00257
00258 return true;
00259 }
00260
00261 bool vil1_bmp_generic_image::write_header()
00262 {
00263 #ifdef DEBUG
00264 vcl_cerr << "Writing BMP header\n"
00265 << width() << 'x' << height() << '@'
00266 << components() << 'x' << bits_per_component() << '\n';
00267 #endif
00268
00269 int rowlen = width() * components() * bits_per_component() / 8;
00270 rowlen += (3-(rowlen-1)%4);
00271 int data_size = height() * rowlen;
00272
00273 if (components() == 1)
00274 info_hdr.colorcount = info_hdr.colormapsize = 1<<bits_per_component();
00275 file_hdr.bitmap_offset = bit_map_start = 54L + 4 * info_hdr.colormapsize;
00276 file_hdr.file_size = bit_map_start+data_size;
00277 core_hdr.header_size = 40;
00278 core_hdr.width = width();
00279 core_hdr.height = height();
00280 core_hdr.bitsperpixel = components()*bits_per_component();
00281 info_hdr.bitmap_size = data_size;
00282
00283 is_->seek(0L);
00284 file_hdr.write(is_);
00285 core_hdr.write(is_);
00286 info_hdr.write(is_);
00287 if (components() == 1)
00288 for (int i=0; i<(1<<bits_per_component()); ++i)
00289 for (int j=0; j<4; ++j)
00290 {
00291 unsigned char c = i;
00292 is_->write(&c,1L);
00293 }
00294
00295 return true;
00296 }
00297
00298
00299
00300 bool vil1_bmp_generic_image::get_section(void* ib, int x0, int y0, int w, int h) const
00301 {
00302 assert(ib != 0);
00303 char *bp = static_cast<char*>(ib);
00304
00305
00306 unsigned bytes_per_pixel = core_hdr.bitsperpixel / 8;
00307 assert(core_hdr.bitsperpixel == 8 || core_hdr.bitsperpixel == 24);
00308
00309
00310
00311 unsigned have_bytes_per_raster = ((bytes_per_pixel * core_hdr.width + 3)>>2)<<2;
00312
00313
00314 unsigned long want_bytes_per_raster = w*bytes_per_pixel;
00315
00316
00317
00318
00319
00320 for (int i=0; i<h; ++i) {
00321 is_->seek(bit_map_start + have_bytes_per_raster*(i+y0) + x0*bytes_per_pixel);
00322 is_->read(bp + want_bytes_per_raster*i, want_bytes_per_raster);
00323 }
00324
00325 return true;
00326 }
00327
00328
00329 bool vil1_bmp_generic_image::put_section(void const *ib, int x0, int y0, int xs, int ys)
00330 {
00331 assert(ib != 0);
00332 int bypp = (components() * bits_per_component() +7) / 8;
00333 int rowlen = width() * bypp;
00334 rowlen += (3-(rowlen-1)%4);
00335
00336 int skip_rows = height()-y0-ys;
00337
00338 for (int y=0; y<ys; ++y,++skip_rows)
00339 {
00340 is_->seek(bit_map_start+skip_rows*rowlen+x0*bypp);
00341 is_->write(((char const*)ib)+y*xs*bypp, xs*bypp);
00342 }
00343
00344 return true;
00345 }