00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008 #include "vil_pnm.h"
00009
00010 #include <vcl_cassert.h>
00011 #include <vcl_cstdio.h>
00012 #include <vcl_vector.h>
00013
00014 #include <vcl_iostream.h>
00015 #include <vcl_cstring.h>
00016
00017 #include <vxl_config.h>
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
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
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;
00140
00141 write_header();
00142 }
00143
00144 vil_pnm_image::~vil_pnm_image()
00145 {
00146
00147 vs_->unref();
00148 }
00149
00150
00151 static void SkipSpaces(vil_stream* vs, char& temp)
00152 {
00153 while (isws(temp) || temp == '#')
00154 {
00155 if (temp == '#')
00156 while (!iseol(temp))
00157 if (1L > vs->read(&temp,1L)) return;
00158
00159 if (1L > vs->read(&temp,1L)) return;
00160 }
00161 }
00162
00163
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;
00171 }
00172 return n;
00173 }
00174
00175 #if VXL_LITTLE_ENDIAN
00176
00177
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
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
00207 bool vil_pnm_image::read_header()
00208 {
00209 char temp;
00210
00211
00212 vs_->seek(0L);
00213
00214 char buf[3];
00215 if (3L > vs_->read(buf, 3L)) return false;
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
00222 vs_->read(&temp, 1L);
00223
00224
00225 SkipSpaces(vs_,temp);
00226
00227
00228 ni_ = ReadInteger(vs_,temp);
00229
00230
00231 SkipSpaces(vs_,temp);
00232
00233
00234 nj_ = ReadInteger(vs_,temp);
00235
00236
00237 if (magic_ == 1 || magic_ == 4)
00238 maxval_ = 1;
00239 else
00240 {
00241
00242 SkipSpaces(vs_,temp);
00243
00244
00245 maxval_ = ReadInteger(vs_,temp);
00246 }
00247
00248 start_of_data_ = vs_->tell() - 1L;
00249
00250
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:
00267 case 4:
00268 format_ = VIL_PIXEL_FORMAT_BOOL;
00269 break;
00270 case 2:
00271 case 5:
00272 case 3:
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;
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)
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)
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
00408 {
00409 vs_->seek(start_of_data_);
00410
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
00416 for (unsigned t = 0; t < x0*nplanes(); ++t) { int a; (*vs_) >> a; }
00417 for (unsigned x = 0; x < ni; ++x)
00418 {
00419
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
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)
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
00540
00541
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 {
00555 vcl_cerr << "ERROR: pgm: writing rawbits format with > 16bit samples\n";
00556 return false;
00557 }
00558 }
00559 else if (magic_ == 6)
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
00571
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 {
00602 vcl_cerr << "ERROR: pgm: writing rawbits format with > 16bit samples\n";
00603 return false;
00604 }
00605 }
00606 else if (magic_ == 4)
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;
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);
00621 }
00622 for (unsigned x = 0; x < view.ni(); ++x)
00623 {
00624 if ((*bb)(x,y)) a |= 1<<(7-s);
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);
00636 a |= c;
00637 }
00638 vs_->write(&a, 1L);
00639 }
00640 }
00641 }
00642 else
00643 {
00644 if (x0 > 0 || y0 > 0 || view.ni() < ni_ || view.nj() < nj_)
00645 return false;
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 }