Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

vil_pnm.cxx

Go to the documentation of this file.
00001 // This is core/vil/file_formats/vil_pnm.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 
00008 #include "vil_pnm.h"
00009 
00010 #include <vcl_cassert.h>
00011 #include <vcl_cstdio.h> // for sprintf
00012 #include <vcl_vector.h>
00013 
00014 #include <vcl_iostream.h>
00015 #include <vcl_cstring.h>
00016 
00017 #include <vxl_config.h> // for VXL_BIG_ENDIAN and vxl_byte
00018 
00019 #include <vil/vil_property.h>
00020 #include <vil/vil_stream.h>
00021 #include <vil/vil_image_resource.h>
00022 #include <vil/vil_image_view.h>
00023 #include <vil/vil_memory_chunk.h>
00024 
00025 #if 0 // see comment below
00026 # include <vil/vil_rgb.h>
00027 #endif
00028 
00029 char const* vil_pnm_format_tag = "pnm";
00030 
00031 static inline bool iseol(int c)
00032 {
00033   return c == 10 || c == 13;
00034 }
00035 
00036 static inline bool isws(int c)
00037 {
00038   return c == ' ' || c == '\t' || c == 10 || c == 13;
00039 }
00040 
00041 vil_image_resource_sptr vil_pnm_file_format::make_input_image(vil_stream* vs)
00042 {
00043   // Attempt to read header
00044   unsigned char buf[3];
00045   if (vs->read(buf, 3L) != 3L)
00046     return 0;
00047   bool ok = ((buf[0] == 'P') &&
00048              isws(buf[2]) &&
00049              (buf[1] >= '1' && buf[2] <= '6'));
00050   if (!ok)
00051     return 0;
00052 
00053   return new vil_pnm_image(vs);
00054 }
00055 
00056 vil_image_resource_sptr vil_pnm_file_format::make_output_image(vil_stream* vs,
00057                                                                unsigned ni,
00058                                                                unsigned nj,
00059                                                                unsigned nplanes,
00060                                                                vil_pixel_format format)
00061 {
00062   return new vil_pnm_image(vs, ni, nj, nplanes, format);
00063 }
00064 
00065 char const* vil_pnm_file_format::tag() const
00066 {
00067   return vil_pnm_format_tag;
00068 }
00069 
00070 /////////////////////////////////////////////////////////////////////////////
00071 
00072 vil_pnm_image::vil_pnm_image(vil_stream* vs):
00073   vs_(vs)
00074 {
00075   vs_->ref();
00076   read_header();
00077 }
00078 
00079 bool vil_pnm_image::get_property(char const * tag, void * value) const
00080 {
00081   if (vcl_strcmp(vil_property_quantisation_depth, tag)==0)
00082   {
00083     if (value)
00084       *static_cast<unsigned int*>(value) = bits_per_component_;
00085     return true;
00086   }
00087 
00088   return false;
00089 }
00090 
00091 char const* vil_pnm_image::file_format() const
00092 {
00093   return vil_pnm_format_tag;
00094 }
00095 
00096 vil_pnm_image::vil_pnm_image(vil_stream* vs, unsigned ni, unsigned nj,
00097                              unsigned nplanes, vil_pixel_format format):
00098   vs_(vs)
00099 {
00100   vs_->ref();
00101   ni_ = ni;
00102   nj_ = nj;
00103 
00104   ncomponents_ = nplanes;
00105   format_ = vil_pixel_format_component_format(format);
00106   if (nplanes == 1 &&
00107       (format==VIL_PIXEL_FORMAT_RGB_BYTE ||
00108        format==VIL_PIXEL_FORMAT_RGB_SBYTE ||
00109        format==VIL_PIXEL_FORMAT_RGB_INT_16 ||
00110        format==VIL_PIXEL_FORMAT_RGB_INT_16 ||
00111        format==VIL_PIXEL_FORMAT_RGB_INT_32 ||
00112        format==VIL_PIXEL_FORMAT_RGB_INT_32 ||
00113        format==VIL_PIXEL_FORMAT_RGB_FLOAT ||
00114        format==VIL_PIXEL_FORMAT_RGB_DOUBLE
00115      ))
00116     ncomponents_ = 3;
00117   if (format==VIL_PIXEL_FORMAT_BOOL)
00118     bits_per_component_ = 1;
00119   else
00120     bits_per_component_ = 8*vil_pixel_format_sizeof_components(format);
00121 
00122   if (ncomponents_ == 3)
00123     magic_ = 6;
00124   else if (ncomponents_ == 1)
00125   {
00126     if (bits_per_component_ == 1)
00127       magic_ = 4;
00128     else
00129       magic_ = 5;
00130   }
00131   else assert(!"nplanes must be 1 or 3");
00132 
00133   // pnm allows 16 bit samples in rawbits format, stored MSB, but not 32 bit.
00134   if (bits_per_component_ > 16) magic_ -= 3;
00135 
00136   if (bits_per_component_ < 31)
00137     maxval_ = (1L<<bits_per_component_)-1;
00138   else
00139     maxval_ = 0x7FFFFFFF; // not 0xFFFFFFFF as the pnm format does not allow values > MAX_INT
00140 
00141   write_header();
00142 }
00143 
00144 vil_pnm_image::~vil_pnm_image()
00145 {
00146   //delete vs_;
00147   vs_->unref();
00148 }
00149 
00150 // Skip over spaces and comments; temp is the current vs character
00151 static void SkipSpaces(vil_stream* vs, char& temp)
00152 {
00153   while (isws(temp) || temp == '#')
00154   {
00155     if (temp == '#') // skip this line:
00156       while (!iseol(temp))
00157         if (1L > vs->read(&temp,1L)) return; // at end-of-file?
00158     // skip this `whitespace' byte by reading the next byte:
00159     if (1L > vs->read(&temp,1L)) return;
00160   }
00161 }
00162 
00163 // Get a nonnegative integer from the vs stream; temp is the current vs byte
00164 static int ReadInteger(vil_stream* vs, char& temp)
00165 {
00166   int n = 0;
00167   while ((temp >= '0') && (temp <= '9'))
00168   {
00169     n *= 10; n += (temp - '0');
00170     if (1L > vs->read(&temp,1L)) return n; // at end-of-file?
00171   }
00172   return n;
00173 }
00174 
00175 #if VXL_LITTLE_ENDIAN
00176 
00177 // Convert the buffer of 16 bit words from MSB to host order
00178 static void ConvertMSBToHost( void* buf, int num_words )
00179 {
00180   unsigned char* ptr = static_cast<unsigned char*>(buf);
00181   for ( int i=0; i < num_words; ++i )
00182   {
00183     unsigned char t = *ptr;
00184     *ptr = *(ptr+1);
00185     *(ptr+1) = t;
00186     ptr += 2;
00187   }
00188 }
00189 
00190 // Convert the buffer of 16 bit words from host order to MSB
00191 static void ConvertHostToMSB( void* buf, int num_words )
00192 {
00193   unsigned char* ptr = static_cast<unsigned char*>(buf);
00194   for ( int i=0; i < num_words; ++i )
00195   {
00196     unsigned char t = *ptr;
00197     *ptr = *(ptr+1);
00198     *(ptr+1) = t;
00199     ptr += 2;
00200   }
00201 }
00202 
00203 #endif // VXL_LITTLE_ENDIAN
00204 
00205 
00206 //: This method accepts any valid PNM file (first 3 bytes "P1\n" to "P6\n")
00207 bool vil_pnm_image::read_header()
00208 {
00209   char temp;
00210 
00211   // Go to start of file
00212   vs_->seek(0L);
00213 
00214   char buf[3];
00215   if (3L > vs_->read(buf, 3L)) return false; // at end-of-file?
00216   if (buf[0] != 'P') return false;
00217   if (!isws(buf[2])) return false;
00218   magic_ = buf[1] - '0';
00219   if (magic_ < 1 || magic_ > 6) return false;
00220 
00221   // read 1 byte
00222   vs_->read(&temp, 1L);
00223 
00224   //Skip over spaces and comments
00225   SkipSpaces(vs_,temp);
00226 
00227   //Read in Width
00228   ni_ = ReadInteger(vs_,temp);
00229 
00230   //Skip over spaces and comments
00231   SkipSpaces(vs_,temp);
00232 
00233   //Read in Height
00234   nj_ = ReadInteger(vs_,temp);
00235 
00236   // a pbm (bitmap) image does not have a maxval field
00237   if (magic_ == 1 || magic_ == 4)
00238     maxval_ = 1;
00239   else
00240   {
00241     //Skip over spaces and comments
00242     SkipSpaces(vs_,temp);
00243 
00244     //Read in Maxval
00245     maxval_ = ReadInteger(vs_,temp);
00246   }
00247 
00248   start_of_data_ = vs_->tell() - 1L;
00249 
00250   //Final end-of-line or other white space (1 byte) before the data section begins
00251   if (isws(temp))
00252     ++start_of_data_;
00253 
00254   ncomponents_ = ((magic_ == 3 || magic_ == 6) ? 3 : 1);
00255 
00256   if (magic_ == 1 || magic_ == 4) bits_per_component_ = 1;
00257   else if (maxval_ == 0) assert(!"problem reading maxval from PNM file");
00258   else if (maxval_ <= 0xFF) bits_per_component_ = 8;
00259   else if (maxval_ <= 0xFFFF) bits_per_component_ = 16;
00260   else if (maxval_ <= 0xFFFFFF) bits_per_component_ = 24;
00261   else if (maxval_ <= 0x7FFFFFFF) bits_per_component_ = 32;
00262   else assert(!"vil_pnm_image: maxval is too big");
00263 
00264   switch (magic_)
00265   {
00266   case 1:  // pbm format
00267   case 4:
00268     format_ = VIL_PIXEL_FORMAT_BOOL;
00269     break;
00270   case 2:  // pgm format
00271   case 5:
00272   case 3:  // ppm format
00273   case 6:
00274     if (bits_per_component_ <= 8)
00275       format_ = VIL_PIXEL_FORMAT_BYTE;
00276     else if (bits_per_component_ <= 16)
00277       format_ = VIL_PIXEL_FORMAT_UINT_16;
00278     else
00279       format_ = VIL_PIXEL_FORMAT_UINT_32;
00280   }
00281 
00282   return true;
00283 }
00284 
00285 bool vil_pnm_image::write_header()
00286 {
00287   vs_->seek(0L);
00288 
00289   char buf[1024];
00290   vcl_sprintf(buf, "P%d\n#vil pnm image, #c=%u, bpc=%u\n%u %u\n",
00291               magic_, ncomponents_, bits_per_component_, ni_, nj_);
00292   vs_->write(buf, vcl_strlen(buf));
00293   if (magic_ != 1 && magic_ != 4)
00294   {
00295     vcl_sprintf(buf, "%lu\n", maxval_);
00296     vs_->write(buf, vcl_strlen(buf));
00297   }
00298   start_of_data_ = vs_->tell();
00299   return true;
00300 }
00301 
00302 static bool operator>>(vil_stream& vs, int& a)
00303 {
00304   char c; vs.read(&c,1L);
00305   SkipSpaces(&vs,c);
00306   if (c < '0' || c > '9') return false; // non-digit found
00307   a = ReadInteger(&vs,c);
00308   return true;
00309 }
00310 
00311 vil_image_view_base_sptr vil_pnm_image::get_copy_view(
00312   unsigned x0, unsigned ni, unsigned y0, unsigned nj) const
00313 {
00314   bool* bb = 0;
00315   unsigned char* ib = 0;
00316   unsigned short* jb = 0;
00317   unsigned int* kb = 0;
00318 
00319   vil_memory_chunk_sptr buf;
00320 
00321   if (bits_per_component_ == 1)
00322   {
00323     buf = new vil_memory_chunk(ni * nj* nplanes() * sizeof(bool),VIL_PIXEL_FORMAT_BOOL);
00324     bb = reinterpret_cast<bool *>(buf->data());
00325   }
00326   else if (bits_per_component_ <= 8)
00327   {
00328     buf = new vil_memory_chunk(ni * nj* nplanes() * 1,VIL_PIXEL_FORMAT_BYTE);
00329     ib = reinterpret_cast<vxl_byte*>(buf->data());
00330   }
00331   else if (bits_per_component_ <= 16)
00332   {
00333     buf = new vil_memory_chunk(ni * nj* nplanes() * 2,VIL_PIXEL_FORMAT_UINT_16);
00334     jb = reinterpret_cast<vxl_uint_16*>(buf->data());
00335   }
00336   else
00337   {
00338     buf = new vil_memory_chunk(ni * nj* nplanes() * 4,VIL_PIXEL_FORMAT_UINT_32);
00339     kb = reinterpret_cast<vxl_uint_32*>(buf->data());
00340   }
00341 
00342   if (magic_ > 4) // pgm or ppm raw image
00343   {
00344     unsigned bytes_per_sample = (bits_per_component_+7)/8;
00345     unsigned bytes_per_pixel = nplanes() * bytes_per_sample;
00346     vil_streampos byte_start = start_of_data_ + (y0 * ni_ + x0) * bytes_per_pixel;
00347     unsigned byte_width = ni_ * bytes_per_pixel;
00348     unsigned byte_out_width = ni * bytes_per_pixel;
00349 
00350     for (unsigned y = 0; y < nj; ++y)
00351     {
00352       vs_->seek(byte_start);
00353       vs_->read((unsigned char *)buf->data() + y * byte_out_width, byte_out_width);
00354       byte_start += byte_width;
00355     }
00356     if ( bytes_per_sample > 2 )
00357     {
00358       vcl_cerr << "ERROR: pnm: reading rawbits format with > 16bit samples\n";
00359       return 0;
00360     }
00361 #if VXL_LITTLE_ENDIAN
00362     else if ( bytes_per_sample==2 )
00363       ConvertMSBToHost( reinterpret_cast<unsigned char *>(buf->data()), ni*nj*nplanes() );
00364 #endif
00365 #if 0 // see comment below
00366     if (ncomponents_ == 1) {
00367 #endif
00368       if (bits_per_component_ <= 1)
00369         return new vil_image_view<bool>(buf, bb, ni, nj, nplanes(), nplanes(), ni*nplanes(), 1);
00370       if (bits_per_component_ <= 8)
00371         return new vil_image_view<vxl_byte>(buf, ib, ni, nj, nplanes(), nplanes(), ni*nplanes(), 1);
00372       else if (bits_per_component_ <= 16)
00373         return new vil_image_view<vxl_uint_16>(buf, jb, ni, nj, nplanes(), nplanes(), ni*nplanes(), 1);
00374       else
00375         return new vil_image_view<vxl_uint_32>(buf, kb, ni, nj, nplanes(), nplanes(), ni*nplanes(), 1);
00376 #if 0 // never return vil_image_view<vil_rgb<T> > : default image representation is planar
00377     } else if (ncomponents_ == 3) {
00378       if (bits_per_component_ <= 8)
00379         return new vil_image_view<vil_rgb<vxl_byte> >(buf, (vil_rgb<vxl_byte>*)ib, ni, nj, 1, 1, ni, 1);
00380       else if (bits_per_component_ <= 16)
00381         return new vil_image_view<vil_rgb<vxl_uint_16> >(buf, (vil_rgb<vxl_uint_16>*)jb, ni, nj, 1, 1, ni, 1);
00382       else
00383         return new vil_image_view<vil_rgb<vxl_uint_32> >(buf, (vil_rgb<vxl_uint_32>*)kb, ni, nj, 1, 1, ni, 1);
00384     } else return 0;
00385 #endif // 0
00386   } else if (magic_ == 4) // pbm (bitmap) raw image
00387   {
00388     unsigned byte_width = (ni_+7)/8;
00389 
00390     for (unsigned y = 0; y < nj; ++y)
00391     {
00392       vil_streampos byte_start = start_of_data_ + (y0+y) * byte_width + x0/8;
00393       vs_->seek(byte_start);
00394       unsigned char a; vs_->read(&a, 1L);
00395       for (unsigned x = 0; x < ni+x0; ++x)
00396       {
00397         if ( x >= x0 )
00398           bb[y * ni + x-x0] = (a & 0x80) != 0;
00399         a <<= 1;
00400         if (x%8 == 7)
00401           vs_->read(&a, 1L);
00402       }
00403     }
00404     assert (buf->size() == ni*nj*sizeof(bool));
00405     return new vil_image_view<bool>(buf, bb, ni, nj, 1, 1, ni, ni*nj);
00406   }
00407   else // ascii (non-raw) image data
00408   {
00409     vs_->seek(start_of_data_);
00410     //0. Skip to the starting line
00411     //
00412     for (unsigned t = 0; t < y0*ni_*nplanes(); ++t) { int a; (*vs_) >> a; }
00413     for (unsigned y = 0; y < nj; ++y)
00414     {
00415       // 1. Skip to column x0
00416       for (unsigned t = 0; t < x0*nplanes(); ++t) { int a; (*vs_) >> a; }
00417       for (unsigned x = 0; x < ni; ++x)
00418       {
00419         // 3. Read the data
00420         if (bits_per_component_ <= 1)
00421           for (unsigned p = 0; p < nplanes(); ++p) { int a; (*vs_) >> a; *(bb++)=(a!=0); }
00422         else if (bits_per_component_ <= 8)
00423           for (unsigned p = 0; p < nplanes(); ++p) { int a; (*vs_) >> a; *(ib++)=a; }
00424         else if (bits_per_component_ <= 16)
00425           for (unsigned p = 0; p < nplanes(); ++p) { int a; (*vs_) >> a; *(jb++)=a; }
00426         else
00427           for (unsigned p = 0; p < nplanes(); ++p) { int a; (*vs_) >> a; *(kb++)=a; }
00428       }
00429       // 5. Skip to the next line
00430       for (unsigned t = 0; t < (ni_-x0-ni)*nplanes(); ++t) { int a; (*vs_) >> a; }
00431     }
00432 #if 0 // see comment below
00433     if (ncomponents_ == 1)
00434     {
00435 #endif
00436       if (bits_per_component_ <= 1)
00437         return new vil_image_view<bool>(buf, reinterpret_cast<bool*>(buf->data()), ni, nj, nplanes(), nplanes(), ni*nplanes(), 1);
00438       if (bits_per_component_ <= 8)
00439         return new vil_image_view<vxl_byte>(buf,reinterpret_cast<vxl_byte*>(buf->data()),ni,nj,nplanes(),nplanes(),ni*nplanes(),1);
00440       else if (bits_per_component_ <= 16)
00441        return new
00442          vil_image_view<vxl_uint_16>(buf,reinterpret_cast<vxl_uint_16*>(buf->data()),ni,nj,nplanes(),nplanes(),ni*nplanes(),1);
00443       else
00444        return new
00445          vil_image_view<vxl_uint_32>(buf,reinterpret_cast<vxl_uint_32*>(buf->data()),ni,nj,nplanes(),nplanes(),ni*nplanes(),1);
00446 #if 0 // never return vil_image_view<vil_rgb<T> > : default image representation is planar
00447     }
00448     else if (ncomponents_ == 3)
00449     {
00450       if (bits_per_component_ <= 8)
00451         return new vil_image_view<vil_rgb<vxl_byte> >(buf, reinterpret_cast<vil_rgb<vxl_byte>*>(buf->data()), ni,nj,1, 1,ni,1);
00452       else if (bits_per_component_ <= 16)
00453        return new vil_image_view<vil_rgb<vxl_uint_16> >(buf,reinterpret_cast<vil_rgb<vxl_uint_16>*>(buf->data()),ni,nj,1,1,ni,1);
00454       else
00455        return new vil_image_view<vil_rgb<vxl_uint_32> >(buf,reinterpret_cast<vil_rgb<vxl_uint_32>*>(buf->data()),ni,nj,1,1,ni,1);
00456     }
00457     else return 0;
00458 #endif // 0
00459   }
00460 }
00461 
00462 
00463 static void operator<<(vil_stream& vs, int a)
00464 {
00465   char buf[128]; vcl_sprintf(buf, " %d\n", a); vs.write(buf,vcl_strlen(buf));
00466 }
00467 
00468 bool vil_pnm_image::put_view(const vil_image_view_base& view,
00469                              unsigned x0, unsigned y0)
00470 {
00471   if (!view_fits(view, x0, y0))
00472   {
00473     vcl_cerr << "ERROR: " << __FILE__ << ":\n view does not fit\n";
00474     return false;
00475   }
00476 
00477   if ((view.pixel_format() == VIL_PIXEL_FORMAT_UINT_32 && bits_per_component_ < 32) ||
00478       (view.pixel_format() == VIL_PIXEL_FORMAT_INT_32  && bits_per_component_ < 32) ||
00479       (view.pixel_format() == VIL_PIXEL_FORMAT_UINT_16 && bits_per_component_ < 16) ||
00480       (view.pixel_format() == VIL_PIXEL_FORMAT_INT_16  && bits_per_component_ < 16) ||
00481       (view.pixel_format() == VIL_PIXEL_FORMAT_BYTE    && bits_per_component_ <  8) ||
00482       (view.pixel_format() == VIL_PIXEL_FORMAT_SBYTE   && bits_per_component_ <  8) ||
00483       (view.pixel_format() == VIL_PIXEL_FORMAT_BOOL    && bits_per_component_ <  1) ||
00484        view.pixel_format() == VIL_PIXEL_FORMAT_DOUBLE ||
00485        view.pixel_format() == VIL_PIXEL_FORMAT_FLOAT )
00486   {
00487     vcl_cerr << "ERROR: " << __FILE__ << ":\n Can't fit view into pnm component size\n";
00488     return false;
00489   }
00490 
00491   const vil_image_view<bool>*  bb=0;
00492   const vil_image_view<vxl_byte>*  ob = 0;
00493   const vil_image_view<vxl_uint_16>* pb = 0;
00494   const vil_image_view<vxl_uint_32>*   qb = 0;
00495 
00496   if (view.pixel_format() == VIL_PIXEL_FORMAT_BOOL)
00497     bb = &static_cast<const vil_image_view<bool>& >(view);
00498   else if (view.pixel_format() == VIL_PIXEL_FORMAT_BYTE)
00499     ob = &static_cast<const vil_image_view<vxl_byte>& >(view);
00500   else if (view.pixel_format() == VIL_PIXEL_FORMAT_UINT_16)
00501     pb = &static_cast<const vil_image_view<vxl_uint_16>& >(view);
00502   else if (view.pixel_format() == VIL_PIXEL_FORMAT_UINT_32)
00503     qb = &static_cast<const vil_image_view<vxl_uint_32>& >(view);
00504   else
00505   {
00506     vcl_cerr << "ERROR: " << __FILE__ << ":\n Do not support putting "
00507              << view.is_a() << " views into pnm image_resource objects\n";
00508     return false;
00509   }
00510 
00511   if (magic_ == 5) // pgm raw image ==> nplanes() == 1
00512   {
00513     unsigned bytes_per_sample = (bits_per_component_+7)/8;
00514     unsigned bytes_per_pixel = bytes_per_sample;
00515     vil_streampos byte_start = start_of_data_ + (y0 * ni_ + x0) * bytes_per_pixel;
00516     unsigned byte_width = ni_ * bytes_per_pixel;
00517     unsigned byte_out_width = view.ni() * bytes_per_pixel;
00518 
00519     if ( bytes_per_sample==1 )
00520     {
00521       assert(ob!=0);
00522       for (unsigned y = 0; y < view.nj(); ++y)
00523       {
00524         vs_->seek(byte_start);
00525         vs_->write(ob->top_left_ptr() + y * view.ni(), byte_out_width);
00526         byte_start += byte_width;
00527       }
00528     } else if ( bytes_per_sample==2 && VXL_BIG_ENDIAN )
00529     {
00530       assert(pb!=0);
00531       for (unsigned y = 0; y < view.nj(); ++y)
00532       {
00533         vs_->seek(byte_start);
00534         vs_->write(pb->top_left_ptr() + y * view.ni(), byte_out_width);
00535         byte_start += byte_width;
00536       }
00537     } else if ( bytes_per_sample==2 )
00538     {
00539       // Little endian host; must convert words to have MSB first.
00540       //
00541       // Convert line by line to avoid duplicating a potentially large image.
00542       vcl_vector<vxl_byte> tempbuf(byte_out_width);
00543       assert(pb!=0);
00544       for (unsigned y = 0; y < view.nj(); ++y)
00545       {
00546         vs_->seek(byte_start);
00547         vcl_memcpy(&tempbuf[0], pb->top_left_ptr() + y * view.ni(), byte_out_width);
00548 #if VXL_LITTLE_ENDIAN
00549         ConvertHostToMSB(&tempbuf[0], view.ni());
00550 #endif
00551         vs_->write(&tempbuf[0], byte_out_width);
00552         byte_start += byte_width;
00553       }
00554     } else { // This should never occur...
00555       vcl_cerr << "ERROR: pgm: writing rawbits format with > 16bit samples\n";
00556       return false;
00557     }
00558   }
00559   else if (magic_ == 6) // ppm raw image; cannot be written as efficiently as pgm
00560   {
00561     unsigned bytes_per_sample = (bits_per_component_+7)/8;
00562     unsigned bytes_per_pixel = nplanes() * bytes_per_sample;
00563     vil_streampos byte_start = start_of_data_ + (y0 * ni_ + x0) * bytes_per_pixel;
00564     unsigned byte_width = ni_ * bytes_per_pixel;
00565 
00566     if ( bytes_per_sample==1 )
00567     {
00568       assert(ob!=0);
00569 
00570       // capes_at_robots - Modified to write a scan-line at once. Writing single bytes
00571       // to disk was extremely slow.
00572       vcl_vector<vxl_byte> scanline( byte_width );
00573 
00574       for (unsigned y = 0; y < view.nj(); ++y)
00575       {
00576         vs_->seek(byte_start);
00577         for (unsigned x = 0, c = 0; x < view.ni(); ++x)
00578           for (unsigned p = 0; p < ncomponents_; ++p, ++c)
00579             scanline[c] = (*ob)(x,y,p);
00580         vs_->write(&scanline[0], byte_width);
00581         byte_start += byte_width;
00582       }
00583     } else if ( bytes_per_sample==2 )
00584     {
00585       assert(pb!=0);
00586       for (unsigned y = y0; y < view.nj(); ++y)
00587       {
00588         vs_->seek(byte_start);
00589         for (unsigned x = x0; x < view.ni(); ++x)
00590         {
00591           vxl_uint_16 tempbuf[3];
00592           for (unsigned p = 0; p < ncomponents_; ++p)
00593             tempbuf[p] = (*pb)(x,y,p);
00594 #if VXL_LITTLE_ENDIAN
00595           ConvertHostToMSB(tempbuf, ncomponents_);
00596 #endif
00597           vs_->write(tempbuf, bytes_per_pixel);
00598         }
00599         byte_start += byte_width;
00600       }
00601     } else { // This should never occur...
00602       vcl_cerr << "ERROR: pgm: writing rawbits format with > 16bit samples\n";
00603       return false;
00604     }
00605   }
00606   else if (magic_ == 4) // pbm (bitmap) raw image
00607   {
00608     int byte_width = (ni_+7)/8;
00609 
00610     assert(bb!=0);
00611     for (unsigned y = 0; y < view.nj(); ++y)
00612     {
00613       vil_streampos byte_start = start_of_data_ + (y0+y) * byte_width + x0/8;
00614       int s = x0&7; // = x0%8;
00615       unsigned char a = 0;
00616       if (s)
00617       {
00618         vs_->read(&a, 1L);
00619         vs_->seek(byte_start);
00620         a &= ((1<<s)-1)<<(8-s); // clear the last 8-s bits of a
00621       }
00622       for (unsigned x = 0; x < view.ni(); ++x)
00623       {
00624         if ((*bb)(x,y)) a |= 1<<(7-s); // single bit; high bit = first
00625         if (s >= 7) { vs_->write(&a, 1L); ++byte_start; s = 0; a = 0; }
00626         else ++s;
00627       }
00628       if (s)
00629       {
00630         if (x0+view.ni() < ni_)
00631         {
00632           vs_->seek(byte_start);
00633           unsigned char c; vs_->read(&c, 1L);
00634           vs_->seek(byte_start);
00635           c &= ((1<<(8-s))-1); // clear the first s bits of c
00636           a |= c;
00637         }
00638         vs_->write(&a, 1L);
00639       }
00640     }
00641   }
00642   else // ascii (non-raw) image data
00643   {
00644     if (x0 > 0 || y0 > 0 || view.ni() < ni_ || view.nj() < nj_)
00645       return false; // can only write the full image in this mode
00646     vs_->seek(start_of_data_);
00647     for (unsigned y = 0; y < view.nj(); ++y)
00648       for (unsigned x = 0; x < view.ni(); ++x)
00649         for (unsigned p = 0; p < ncomponents_; ++p)
00650         {
00651           if (bits_per_component_ <= 1)       (*vs_) << (*bb)(x,y,p);
00652           else if (bits_per_component_ <= 8)  (*vs_) << (*ob)(x,y,p);
00653           else if (bits_per_component_ <= 16) (*vs_) << (*pb)(x,y,p);
00654           else                                (*vs_) << (*qb)(x,y,p);
00655         }
00656   }
00657 
00658   return true;
00659 }

Generated on Thu Jan 10 14:40:00 2008 for core/vil by  doxygen 1.4.4