core/vil1/file_formats/vil1_gif.cxx

Go to the documentation of this file.
00001 // This is core/vil1/file_formats/vil1_gif.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author fsm
00008 
00009 #include "vil1_gif.h"
00010 
00011 #include <vcl_cassert.h>
00012 #include <vcl_iomanip.h> // for vcl_hex, vcl_dec
00013 #include <vcl_iostream.h>
00014 #include <vcl_cstring.h>
00015 #include <vcl_cctype.h> // for vcl_isprint
00016 
00017 #include <vil1/vil1_stream.h>
00018 #include <vil1/vil1_16bit.h>
00019 #include <vil1/vil1_property.h>
00020 
00021 #ifndef VERBOSE // set this to 1 on the compile line if you want verbose output
00022 #define VERBOSE 0
00023 #endif
00024 
00025 bool vil1_gif_probe(vil1_stream *s)
00026 {
00027   // 47 49 46 38 37 61  "GIF87a"
00028   s->seek(0L);
00029   char magic[6];
00030   s->read(magic, sizeof magic);
00031 
00032   if (magic[0] != 0x47 ||
00033       magic[1] != 0x49 ||
00034       magic[2] != 0x46 )
00035     return false;
00036 
00037   if (magic[3] != 0x38 ||
00038       magic[4] != 0x37 ||
00039       magic[5] != 0x61 ) {
00040     vcl_cerr << __FILE__ ": file format may be GIF, but is not v87\n";
00041     // may be GIF, but not GIF87a
00042     return false;
00043   }
00044   return true;
00045 }
00046 
00047 char const *vil1_gif_file_format::tag() const { return "gif"; }
00048 
00049 vil1_image_impl *vil1_gif_file_format::make_input_image(vil1_stream *s)
00050 {
00051   if (! vil1_gif_probe(s))
00052     return 0;
00053   else
00054     return new vil1_gif_loader_saver(s);
00055 }
00056 
00057 vil1_image_impl *vil1_gif_file_format::make_output_image(vil1_stream*, int, int, int, int, int, vil1_component_format)
00058 {
00059   vcl_cerr << "GIF writer not yet implemented\n";
00060   return 0;
00061 }
00062 
00063 bool vil1_gif_loader_saver::get_property(char const *tag, void *prop) const
00064 {
00065   if (0==vcl_strcmp(tag, vil1_property_top_row_first))
00066     return prop ? (*(bool*)prop) = true : true;
00067 
00068   if (0==vcl_strcmp(tag, vil1_property_left_first))
00069     return prop ? (*(bool*)prop) = true : true;
00070 
00071   return false;
00072 }
00073 
00074 vil1_gif_loader_saver::vil1_gif_loader_saver(vil1_stream *s_)
00075  : s(s_), is_grey(false)
00076 {
00077   s->ref();
00078   assert(vil1_gif_probe(s));
00079 
00080   s->seek(6L);
00081 
00082   // read screen descriptor
00083   screen_width_  = vil1_16bit_read_little_endian(s);
00084   screen_height_ = vil1_16bit_read_little_endian(s);
00085 #if VERBOSE
00086   vcl_cerr << "screen width and height : "
00087            << screen_width_ << ' ' << screen_height_ << vcl_endl;
00088 #endif
00089 
00090   unsigned char b;
00091 
00092   // ---------- read screen descriptor
00093 
00094   {
00095     s->read(&b, 1L);
00096 #if VERBOSE
00097     vcl_cerr << "b = 0x" << vcl_hex << int(b) << vcl_dec << vcl_endl;
00098 #endif
00099 
00100     int bits_of_colour_res;
00101     if (b & 0x80) {
00102       bits_of_colour_res = 1 + ((b & 0x70)>>4);
00103 #if VERBOSE
00104       vcl_cerr << "screen has global colour map\n"
00105                << "screen has " << bits_of_colour_res << " bits of colour resolution\n";
00106 #endif
00107     }
00108     else
00109       bits_of_colour_res = 0;
00110 
00111     // bit 3 should be zero
00112     if (b & 0x08) {
00113       vcl_cerr << "bit 3 is not zero\n";
00114       assert(!"bit 3 should be zero");
00115     }
00116 
00117     int bits_per_pixel = 1 + (b & 0x07);
00118 #if VERBOSE
00119     vcl_cerr << "screen has " << bits_per_pixel << " bits per pixel\n";
00120 #endif
00121     if (bits_per_pixel != 8) {
00122       vcl_cerr << "cannot read GIF with != 8 bits per pixel.\n";
00123       assert(!"GIF with != 8 bits per pixel not implemented");
00124     }
00125 
00126     // create global colour map, if needed.
00127     if (bits_of_colour_res > 0) {
00128       global_color_map = new vil1_gif_color_map( 0x1 << bits_per_pixel );
00129 #if VERBOSE
00130       vcl_cerr << "global colour map has size " << global_color_map->size << vcl_endl;
00131 #endif
00132     }
00133 
00134     // colour index of background.
00135     s->read(&b, 1L);
00136     background_index = b;
00137 #if VERBOSE
00138     vcl_cerr << "background has colour index " << background_index << vcl_endl;
00139 #endif
00140 
00141     // should be zero
00142     s->read(&b, 1L);
00143     if (b) {
00144       vcl_cerr << "not zero\n";
00145       assert(!"this byte should be zero");
00146     }
00147   }
00148 
00149   // ---------- read global colourmap
00150 
00151 #if VERBOSE
00152   vcl_cerr << "position is 0x" << vcl_hex << s->tell() << vcl_dec << vcl_endl;
00153 #endif
00154   if (global_color_map) {
00155 #if VERBOSE
00156     vcl_cerr << "read global colour map\n";
00157 #endif
00158     s->read(global_color_map->cmap, 3*global_color_map->size);
00159 
00160     is_grey = true;
00161     for (int i=0; is_grey && i<global_color_map->size; ++i)
00162        if (global_color_map->cmap[3*i+0] !=
00163            global_color_map->cmap[3*i+1] ||
00164            global_color_map->cmap[3*i+1] !=
00165            global_color_map->cmap[3*i+2])
00166          is_grey = false;
00167 
00168 #if VERBOSE
00169     for (int i=0; i<16; ++i)
00170       vcl_cerr << vcl_setw(3) << i << ' '
00171                << int((unsigned char) global_color_map->cmap[3*i+0]) << ' '
00172                << int((unsigned char) global_color_map->cmap[3*i+1]) << ' '
00173                << int((unsigned char) global_color_map->cmap[3*i+2]) << '\n';
00174 #endif
00175   }
00176 
00177   // ---------- read image descriptors
00178 
00179   while (true) {
00180     vil1_streampos offset = s->tell();
00181 #if VERBOSE
00182     vcl_cerr << "position is 0x" << vcl_hex << offset << vcl_dec << vcl_endl;
00183 #endif
00184 
00185     // read image separator or GIF terminator
00186     s->read(&b, 1L);
00187     if (b == ';')   // terminator
00188       break;
00189     if (b != ',') { // separator
00190       vcl_cerr << "unexpected character \'";
00191       if (vcl_isprint(b)) {
00192         vcl_cerr << b;
00193       } else {
00194         vcl_cerr << "[unprintable]";
00195       }
00196       vcl_cerr<< "\' (0x" << vcl_hex<< int(b) << vcl_dec<< ") in GIF stream\n";
00197       assert(!"expected GIF separator here");
00198     }
00199 
00200     vil1_gif_image_record *ir = new vil1_gif_image_record;
00201     ir->offset = offset;
00202 
00203     ir->x0 = vil1_16bit_read_little_endian(s);
00204     ir->y0 = vil1_16bit_read_little_endian(s);
00205     ir->w  = vil1_16bit_read_little_endian(s);
00206     ir->h  = vil1_16bit_read_little_endian(s);
00207 #if VERBOSE
00208     vcl_cerr << "x0 y0 w h = " << ir->x0 << ' ' << ir->y0 << ' '
00209              << ir->w << ' ' << ir->h << vcl_endl;
00210 
00211     vcl_cerr << "position is 0x" << vcl_hex << s->tell() << vcl_dec << vcl_endl;
00212 #endif
00213 
00214     s->read(&b, 1L);
00215 #if VERBOSE
00216     vcl_cerr << "b = 0x" << vcl_hex << int(b) << vcl_dec << vcl_endl;
00217 
00218     vcl_cerr << "position is 0x" << vcl_hex << s->tell() << vcl_dec << vcl_endl;
00219 #endif
00220     if (b & 0x80) { // local colour map?
00221       int bits = 1 + (b & 0x07);
00222 #if VERBOSE
00223       vcl_cerr << "image has local colour map\n"
00224                << "read local colour map (" << bits << " bits per pixel)\n";
00225 #endif
00226       ir->color_map = new vil1_gif_color_map(0x1 << bits);
00227       s->read(ir->color_map->cmap, 3*ir->color_map->size);
00228     }
00229     else {
00230 #if VERBOSE
00231       vcl_cerr << "no local colour map\n";
00232 #endif
00233       ir->color_map = 0;
00234     }
00235 #if VERBOSE
00236     vcl_cerr << "position is 0x" << vcl_hex << s->tell() << vcl_dec << vcl_endl;
00237 #endif
00238 
00239     // interlaced or sequential?
00240     ir->interlaced = ( (b & 0x40) != 0 );
00241 #if VERBOSE
00242     vcl_cerr<< "image is "<< (ir->interlaced ? "interlaced\n" : "sequential\n");
00243 #endif
00244     if (ir->interlaced) {
00245       vcl_cerr << "can't read interlaced GIFs yet\n";
00246       assert(!"interlaced GIF reading not implemented");
00247     }
00248 
00249     // bits 543 should be zero
00250     if (b & 0x38) {
00251       vcl_cerr << "bits 543 are not zero\n";
00252       assert(!"incorrect bits 3,4,5");
00253     }
00254 
00255     //
00256     if (ir->color_map) {
00257       ir->bits_per_pixel = 1 + (b & 0x07);
00258 #if VERBOSE
00259       vcl_cerr << "image has " << ir->bits_per_pixel << " bits per pixel\n";
00260 #endif
00261       if (ir->bits_per_pixel != 8) {
00262         vcl_cerr << "cannot cope with " << ir->bits_per_pixel << " bits per pixel\n";
00263         assert(!"bpp != 8 not implemented");
00264       }
00265     }
00266     else
00267       ir->bits_per_pixel = 0;
00268 
00269     //
00270     ir->bitmap_start = s->tell();
00271 
00272     // seek to end of raster data
00273     s->seek(ir->bitmap_start + ir->w * ir->h);
00274 
00275     images.push_back(ir);
00276     break;
00277   }
00278 
00279 #if VERBOSE
00280   vcl_cerr << "read " << images.size() << " image descriptors\n"
00281            << "------------ done : position = "
00282            << vcl_hex << s->tell() << vcl_dec << vcl_endl;
00283 #endif
00284 }
00285 
00286 vil1_gif_loader_saver::~vil1_gif_loader_saver()
00287 {
00288   s->unref();
00289 
00290   if (global_color_map) {
00291     delete global_color_map;
00292     global_color_map = 0;
00293   }
00294 
00295   for (unsigned int i=0; i<images.size(); ++i) {
00296     vil1_gif_image_record *ir = static_cast<vil1_gif_image_record*>(images[i]);
00297     if (ir->color_map)
00298       delete ir->color_map;
00299     delete ir;
00300   }
00301   images.clear();
00302 }
00303 
00304 char const *vil1_gif_loader_saver::file_format() const { return "gif"; }
00305 
00306 vil1_image vil1_gif_loader_saver::get_plane(unsigned int p) const
00307 {
00308   if (p<images.size())
00309     return new vil1_gif_loader_saver_proxy(p, const_cast<vil1_gif_loader_saver*>(this));
00310   else
00311     return 0;
00312 }
00313 
00314 bool vil1_gif_loader_saver::get_section(void *buf, int x0, int y0, int w, int h) const
00315 {
00316   if (planes() == 1)
00317     return get_section(0, buf, x0, y0, w, h);
00318   else
00319     return false;
00320 }
00321 
00322 bool vil1_gif_loader_saver::put_section(void const *buf, int x0, int y0, int w, int h)
00323 {
00324   if (planes() == 1)
00325     return put_section(0, buf, x0, y0, w, h);
00326   else
00327     return false;
00328 }
00329 
00330 bool vil1_gif_loader_saver::get_section(int /*image*/, void* /*buf*/, int /*x0*/, int /*y0*/, int /*w*/, int /*h*/) const
00331 {
00332 #if 1
00333   // Damn! Have to implement LZW decompression here. Maybe some other day.
00334   vcl_cerr << "vil1_gif_loader_saver::get_section(): LZW decompression not yet implemented\n";
00335 #else
00336   assert(0<=image && image<images.size());
00337   char *char_buf = (char*) buf;
00338 
00339   vil1_gif_image_record *ir = static_cast<vil1_gif_image_record*>(images[image]);
00340 
00341 #if 0
00342   for (int i=0; i<h; ++i) {
00343     s->seek(ir->bitmap_start + x0 + ir->w*(y0 + i));
00344     s->read(char_buf + w*i, w);
00345   }
00346 #else
00347   unsigned char *tmp = new unsigned char [w];
00348 
00349   vil1_gif_color_map *cm = ir->color_map ? ir->color_map : global_color_map;
00350 
00351   for (int i=0; i<h; ++i) {
00352     s->seek(ir->bitmap_start + x0 + ir->w*(y0 + i));
00353     s->read(tmp, w);
00354     for (int j=0; j<w; ++j) {
00355       int index = int(tmp[j]);
00356       (char_buf + 3*w*i)[3*j + 0] = cm->cmap[3*index + 0];
00357       (char_buf + 3*w*i)[3*j + 1] = cm->cmap[3*index + 1];
00358       (char_buf + 3*w*i)[3*j + 2] = cm->cmap[3*index + 2];
00359     }
00360   }
00361 
00362   delete [] tmp;
00363 #endif
00364 #endif
00365   return true;
00366 }

Generated on Sat Nov 22 05:08:28 2008 for core/vil1 by  doxygen 1.5.1