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 #include <vil/vil_exception.h>
00025
00026 #if 0 // see comment below
00027 # include <vil/vil_rgb.h>
00028 #endif
00029
00030 char const* vil_pnm_format_tag = "pnm";
00031
00032 static inline bool iseol(int c)
00033 {
00034 return c == 10 || c == 13;
00035 }
00036
00037 static inline bool isws(int c)
00038 {
00039 return c == ' ' || c == '\t' || c == 10 || c == 13;
00040 }
00041
00042 vil_image_resource_sptr vil_pnm_file_format::make_input_image(vil_stream* vs)
00043 {
00044
00045 unsigned char buf[3];
00046 if (vs->read(buf, 3L) != 3L)
00047 return 0;
00048 bool ok = ((buf[0] == 'P') &&
00049 isws(buf[2]) &&
00050 (buf[1] >= '1' && buf[2] <= '6'));
00051 if (!ok)
00052 return 0;
00053
00054 return new vil_pnm_image(vs);
00055 }
00056
00057 vil_image_resource_sptr vil_pnm_file_format::make_output_image(vil_stream* vs,
00058 unsigned ni,
00059 unsigned nj,
00060 unsigned nplanes,
00061 vil_pixel_format format)
00062 {
00063 return new vil_pnm_image(vs, ni, nj, nplanes, format);
00064 }
00065
00066 char const* vil_pnm_file_format::tag() const
00067 {
00068 return vil_pnm_format_tag;
00069 }
00070
00071
00072
00073 vil_pnm_image::vil_pnm_image(vil_stream* vs):
00074 vs_(vs)
00075 {
00076 vs_->ref();
00077 read_header();
00078 }
00079
00080 bool vil_pnm_image::get_property(char const * tag, void * value) const
00081 {
00082 if (vcl_strcmp(vil_property_quantisation_depth, tag)==0)
00083 {
00084 if (value)
00085 *static_cast<unsigned int*>(value) = bits_per_component_;
00086 return true;
00087 }
00088
00089 return false;
00090 }
00091
00092 char const* vil_pnm_image::file_format() const
00093 {
00094 return vil_pnm_format_tag;
00095 }
00096
00097 vil_pnm_image::vil_pnm_image(vil_stream* vs, unsigned ni, unsigned nj,
00098 unsigned nplanes, vil_pixel_format format):
00099 vs_(vs)
00100 {
00101 vs_->ref();
00102 ni_ = ni;
00103 nj_ = nj;
00104
00105 ncomponents_ = nplanes;
00106 format_ = vil_pixel_format_component_format(format);
00107 if (nplanes == 1 &&
00108 (format==VIL_PIXEL_FORMAT_RGB_BYTE ||
00109 format==VIL_PIXEL_FORMAT_RGB_SBYTE ||
00110 format==VIL_PIXEL_FORMAT_RGB_INT_16 ||
00111 format==VIL_PIXEL_FORMAT_RGB_INT_16 ||
00112 format==VIL_PIXEL_FORMAT_RGB_INT_32 ||
00113 format==VIL_PIXEL_FORMAT_RGB_INT_32 ||
00114 format==VIL_PIXEL_FORMAT_RGB_FLOAT ||
00115 format==VIL_PIXEL_FORMAT_RGB_DOUBLE
00116 ))
00117 ncomponents_ = 3;
00118 if (format==VIL_PIXEL_FORMAT_BOOL)
00119 bits_per_component_ = 1;
00120 else
00121 bits_per_component_ = 8*vil_pixel_format_sizeof_components(format);
00122
00123 if (ncomponents_ == 3)
00124 magic_ = 6;
00125 else if (ncomponents_ == 1)
00126 {
00127 if (bits_per_component_ == 1)
00128 magic_ = 4;
00129 else
00130 magic_ = 5;
00131 }
00132 else assert(!"nplanes must be 1 or 3");
00133
00134
00135 if (bits_per_component_ > 16) magic_ -= 3;
00136
00137 if (bits_per_component_ < 31)
00138 maxval_ = (1L<<bits_per_component_)-1;
00139 else
00140 maxval_ = 0x7FFFFFFF;
00141
00142 write_header();
00143 }
00144
00145 vil_pnm_image::~vil_pnm_image()
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 break;
00281 default:
00282 break;
00283 }
00284
00285 return true;
00286 }
00287
00288 bool vil_pnm_image::write_header()
00289 {
00290 vs_->seek(0L);
00291
00292 char buf[1024];
00293 vcl_sprintf(buf, "P%d\n#vil pnm image, #c=%u, bpc=%u\n%u %u\n",
00294 magic_, ncomponents_, bits_per_component_, ni_, nj_);
00295 vs_->write(buf, vcl_strlen(buf));
00296 if (magic_ != 1 && magic_ != 4)
00297 {
00298 vcl_sprintf(buf, "%lu\n", maxval_);
00299 vs_->write(buf, vcl_strlen(buf));
00300 }
00301 start_of_data_ = vs_->tell();
00302 return true;
00303 }
00304
00305 static bool operator>>(vil_stream& vs, int& a)
00306 {
00307 char c; vs.read(&c,1L);
00308 SkipSpaces(&vs,c);
00309 if (c < '0' || c > '9') return false;
00310 a = ReadInteger(&vs,c);
00311 return true;
00312 }
00313
00314 vil_image_view_base_sptr vil_pnm_image::get_copy_view(
00315 unsigned x0, unsigned ni, unsigned y0, unsigned nj) const
00316 {
00317 bool* bb = 0;
00318 unsigned char* ib = 0;
00319 unsigned short* jb = 0;
00320 unsigned int* kb = 0;
00321
00322 vil_memory_chunk_sptr buf;
00323
00324 if (bits_per_component_ == 1)
00325 {
00326 buf = new vil_memory_chunk(ni * nj* nplanes() * sizeof(bool),VIL_PIXEL_FORMAT_BOOL);
00327 bb = reinterpret_cast<bool *>(buf->data());
00328 }
00329 else if (bits_per_component_ <= 8)
00330 {
00331 buf = new vil_memory_chunk(ni * nj* nplanes() * 1,VIL_PIXEL_FORMAT_BYTE);
00332 ib = reinterpret_cast<vxl_byte*>(buf->data());
00333 }
00334 else if (bits_per_component_ <= 16)
00335 {
00336 buf = new vil_memory_chunk(ni * nj* nplanes() * 2,VIL_PIXEL_FORMAT_UINT_16);
00337 jb = reinterpret_cast<vxl_uint_16*>(buf->data());
00338 }
00339 else
00340 {
00341 buf = new vil_memory_chunk(ni * nj* nplanes() * 4,VIL_PIXEL_FORMAT_UINT_32);
00342 kb = reinterpret_cast<vxl_uint_32*>(buf->data());
00343 }
00344
00345 if (magic_ > 4)
00346 {
00347 unsigned bytes_per_sample = (bits_per_component_+7)/8;
00348 unsigned bytes_per_pixel = nplanes() * bytes_per_sample;
00349 vil_streampos byte_start = start_of_data_ + (y0 * ni_ + x0) * bytes_per_pixel;
00350 unsigned byte_width = ni_ * bytes_per_pixel;
00351 unsigned byte_out_width = ni * bytes_per_pixel;
00352
00353 for (unsigned y = 0; y < nj; ++y)
00354 {
00355 vs_->seek(byte_start);
00356 vs_->read((unsigned char *)buf->data() + y * byte_out_width, byte_out_width);
00357 byte_start += byte_width;
00358 }
00359 if ( bytes_per_sample > 2 )
00360 {
00361 vcl_cerr << "ERROR: pnm: reading rawbits format with > 16bit samples\n";
00362 return 0;
00363 }
00364 #if VXL_LITTLE_ENDIAN
00365 else if ( bytes_per_sample==2 )
00366 ConvertMSBToHost( reinterpret_cast<unsigned char *>(buf->data()), ni*nj*nplanes() );
00367 #endif
00368 #if 0 // see comment below
00369 if (ncomponents_ == 1) {
00370 #endif
00371 if (bits_per_component_ <= 1)
00372 return new vil_image_view<bool>(buf, bb, ni, nj, nplanes(), nplanes(), ni*nplanes(), 1);
00373 if (bits_per_component_ <= 8)
00374 return new vil_image_view<vxl_byte>(buf, ib, ni, nj, nplanes(), nplanes(), ni*nplanes(), 1);
00375 else if (bits_per_component_ <= 16)
00376 return new vil_image_view<vxl_uint_16>(buf, jb, ni, nj, nplanes(), nplanes(), ni*nplanes(), 1);
00377 else
00378 return new vil_image_view<vxl_uint_32>(buf, kb, ni, nj, nplanes(), nplanes(), ni*nplanes(), 1);
00379 #if 0 // never return vil_image_view<vil_rgb<T> > : default image representation is planar
00380 }
00381 else if (ncomponents_ == 3) {
00382 if (bits_per_component_ <= 8)
00383 return new vil_image_view<vil_rgb<vxl_byte> >(buf, (vil_rgb<vxl_byte>*)ib, ni, nj, 1, 1, ni, 1);
00384 else if (bits_per_component_ <= 16)
00385 return new vil_image_view<vil_rgb<vxl_uint_16> >(buf, (vil_rgb<vxl_uint_16>*)jb, ni, nj, 1, 1, ni, 1);
00386 else
00387 return new vil_image_view<vil_rgb<vxl_uint_32> >(buf, (vil_rgb<vxl_uint_32>*)kb, ni, nj, 1, 1, ni, 1);
00388 }
00389 else return 0;
00390 #endif // 0
00391 }
00392 else if (magic_ == 4)
00393 {
00394 unsigned byte_width = (ni_+7)/8;
00395
00396 for (unsigned y = 0; y < nj; ++y)
00397 {
00398 vil_streampos byte_start = start_of_data_ + (y0+y) * byte_width + x0/8;
00399 vs_->seek(byte_start);
00400 unsigned char a; vs_->read(&a, 1L);
00401 for (unsigned x = 0; x < ni+x0; ++x)
00402 {
00403 if ( x >= x0 )
00404 bb[y * ni + x-x0] = (a & 0x80) != 0;
00405 a <<= 1;
00406 if (x%8 == 7)
00407 vs_->read(&a, 1L);
00408 }
00409 }
00410 assert (buf->size() == ni*nj*sizeof(bool));
00411 return new vil_image_view<bool>(buf, bb, ni, nj, 1, 1, ni, ni*nj);
00412 }
00413 else
00414 {
00415 vs_->seek(start_of_data_);
00416
00417
00418 for (unsigned t = 0; t < y0*ni_*nplanes(); ++t) { int a; (*vs_) >> a; }
00419 for (unsigned y = 0; y < nj; ++y)
00420 {
00421
00422 for (unsigned t = 0; t < x0*nplanes(); ++t) { int a; (*vs_) >> a; }
00423 for (unsigned x = 0; x < ni; ++x)
00424 {
00425
00426 if (bits_per_component_ <= 1)
00427 for (unsigned p = 0; p < nplanes(); ++p) { int a; (*vs_) >> a; *(bb++)=(a!=0); }
00428 else if (bits_per_component_ <= 8)
00429 for (unsigned p = 0; p < nplanes(); ++p) { int a; (*vs_) >> a; *(ib++)=vxl_byte(a); }
00430 else if (bits_per_component_ <= 16)
00431 for (unsigned p = 0; p < nplanes(); ++p) { int a; (*vs_) >> a; *(jb++)=vxl_uint_16(a); }
00432 else
00433 for (unsigned p = 0; p < nplanes(); ++p) { int a; (*vs_) >> a; *(kb++)=vxl_uint_32(a); }
00434 }
00435
00436 for (unsigned t = 0; t < (ni_-x0-ni)*nplanes(); ++t) { int a; (*vs_) >> a; }
00437 }
00438 #if 0 // see comment below
00439 if (ncomponents_ == 1)
00440 {
00441 #endif
00442 if (bits_per_component_ <= 1)
00443 return new vil_image_view<bool>(buf, reinterpret_cast<bool*>(buf->data()), ni, nj, nplanes(), nplanes(), ni*nplanes(), 1);
00444 if (bits_per_component_ <= 8)
00445 return new vil_image_view<vxl_byte>(buf,reinterpret_cast<vxl_byte*>(buf->data()),ni,nj,nplanes(),nplanes(),ni*nplanes(),1);
00446 else if (bits_per_component_ <= 16)
00447 return new
00448 vil_image_view<vxl_uint_16>(buf,reinterpret_cast<vxl_uint_16*>(buf->data()),ni,nj,nplanes(),nplanes(),ni*nplanes(),1);
00449 else
00450 return new
00451 vil_image_view<vxl_uint_32>(buf,reinterpret_cast<vxl_uint_32*>(buf->data()),ni,nj,nplanes(),nplanes(),ni*nplanes(),1);
00452 #if 0 // never return vil_image_view<vil_rgb<T> > : default image representation is planar
00453 }
00454 else if (ncomponents_ == 3)
00455 {
00456 if (bits_per_component_ <= 8)
00457 return new vil_image_view<vil_rgb<vxl_byte> >(buf, reinterpret_cast<vil_rgb<vxl_byte>*>(buf->data()), ni,nj,1, 1,ni,1);
00458 else if (bits_per_component_ <= 16)
00459 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);
00460 else
00461 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);
00462 }
00463 else return 0;
00464 #endif // 0
00465 }
00466 }
00467
00468
00469 static void operator<<(vil_stream& vs, int a)
00470 {
00471 char buf[128]; vcl_sprintf(buf, " %d\n", a); vs.write(buf,vcl_strlen(buf));
00472 }
00473
00474 bool vil_pnm_image::put_view(const vil_image_view_base& view,
00475 unsigned x0, unsigned y0)
00476 {
00477 if (!view_fits(view, x0, y0))
00478 {
00479 vil_exception_warning(vil_exception_out_of_bounds("vil_pnm_image::put_view"));
00480 return false;
00481 }
00482
00483 if ((view.pixel_format() == VIL_PIXEL_FORMAT_UINT_32 && bits_per_component_ < 32) ||
00484 (view.pixel_format() == VIL_PIXEL_FORMAT_INT_32 && bits_per_component_ < 32) ||
00485 (view.pixel_format() == VIL_PIXEL_FORMAT_UINT_16 && bits_per_component_ < 16) ||
00486 (view.pixel_format() == VIL_PIXEL_FORMAT_INT_16 && bits_per_component_ < 16) ||
00487 (view.pixel_format() == VIL_PIXEL_FORMAT_BYTE && bits_per_component_ < 8) ||
00488 (view.pixel_format() == VIL_PIXEL_FORMAT_SBYTE && bits_per_component_ < 8) ||
00489 (view.pixel_format() == VIL_PIXEL_FORMAT_BOOL && bits_per_component_ < 1) ||
00490 view.pixel_format() == VIL_PIXEL_FORMAT_DOUBLE ||
00491 view.pixel_format() == VIL_PIXEL_FORMAT_FLOAT )
00492 {
00493 vcl_cerr << "ERROR: " << __FILE__ << ":\n Can't fit view into pnm component size\n";
00494 return false;
00495 }
00496
00497 const vil_image_view<bool>* bb=0;
00498 const vil_image_view<vxl_byte>* ob = 0;
00499 const vil_image_view<vxl_uint_16>* pb = 0;
00500 const vil_image_view<vxl_uint_32>* qb = 0;
00501
00502 if (view.pixel_format() == VIL_PIXEL_FORMAT_BOOL)
00503 bb = &static_cast<const vil_image_view<bool>& >(view);
00504 else if (view.pixel_format() == VIL_PIXEL_FORMAT_BYTE)
00505 ob = &static_cast<const vil_image_view<vxl_byte>& >(view);
00506 else if (view.pixel_format() == VIL_PIXEL_FORMAT_UINT_16)
00507 pb = &static_cast<const vil_image_view<vxl_uint_16>& >(view);
00508 else if (view.pixel_format() == VIL_PIXEL_FORMAT_UINT_32)
00509 qb = &static_cast<const vil_image_view<vxl_uint_32>& >(view);
00510 else
00511 {
00512 vcl_cerr << "ERROR: " << __FILE__ << ":\n Do not support putting "
00513 << view.is_a() << " views into pnm image_resource objects\n";
00514 return false;
00515 }
00516
00517 if (magic_ == 5)
00518 {
00519 unsigned bytes_per_sample = (bits_per_component_+7)/8;
00520 unsigned bytes_per_pixel = bytes_per_sample;
00521 vil_streampos byte_start = start_of_data_ + (y0 * ni_ + x0) * bytes_per_pixel;
00522 unsigned byte_width = ni_ * bytes_per_pixel;
00523 unsigned byte_out_width = view.ni() * bytes_per_pixel;
00524
00525 if ( bytes_per_sample==1 )
00526 {
00527 assert(ob!=0);
00528 for (unsigned y = 0; y < view.nj(); ++y)
00529 {
00530 vs_->seek(byte_start);
00531 vs_->write(ob->top_left_ptr() + y * ob->jstep(), byte_out_width);
00532 byte_start += byte_width;
00533 }
00534 }
00535 else if ( bytes_per_sample==2 && VXL_BIG_ENDIAN )
00536 {
00537 assert(pb!=0);
00538 for (unsigned y = 0; y < view.nj(); ++y)
00539 {
00540 vs_->seek(byte_start);
00541 vs_->write(pb->top_left_ptr() + y * pb->jstep(), byte_out_width);
00542 byte_start += byte_width;
00543 }
00544 }
00545 else if ( bytes_per_sample==2 )
00546 {
00547
00548
00549
00550 vcl_vector<vxl_byte> tempbuf(byte_out_width);
00551 assert(pb!=0);
00552 for (unsigned y = 0; y < view.nj(); ++y)
00553 {
00554 vs_->seek(byte_start);
00555 vcl_memcpy(&tempbuf[0], pb->top_left_ptr() + y * pb->jstep(), byte_out_width);
00556 #if VXL_LITTLE_ENDIAN
00557 ConvertHostToMSB(&tempbuf[0], view.ni());
00558 #endif
00559 vs_->write(&tempbuf[0], byte_out_width);
00560 byte_start += byte_width;
00561 }
00562 }
00563 else {
00564 vcl_cerr << "ERROR: pgm: writing rawbits format with > 16bit samples\n";
00565 return false;
00566 }
00567 }
00568 else if (magic_ == 6)
00569 {
00570 unsigned bytes_per_sample = (bits_per_component_+7)/8;
00571 unsigned bytes_per_pixel = nplanes() * bytes_per_sample;
00572 vil_streampos byte_start = start_of_data_ + (y0 * ni_ + x0) * bytes_per_pixel;
00573 unsigned byte_width = ni_ * bytes_per_pixel;
00574
00575 if ( bytes_per_sample==1 )
00576 {
00577 assert(ob!=0);
00578
00579
00580
00581 vcl_vector<vxl_byte> scanline( byte_width );
00582
00583 for (unsigned y = 0; y < view.nj(); ++y)
00584 {
00585 vs_->seek(byte_start);
00586 for (unsigned x = 0, c = 0; x < view.ni(); ++x)
00587 for (unsigned p = 0; p < ncomponents_; ++p, ++c)
00588 scanline[c] = (*ob)(x,y,p);
00589 vs_->write(&scanline[0], byte_width);
00590 byte_start += byte_width;
00591 }
00592 }
00593 else if ( bytes_per_sample==2 )
00594 {
00595 assert(pb!=0);
00596 for (unsigned y = y0; y < view.nj(); ++y)
00597 {
00598 vs_->seek(byte_start);
00599 for (unsigned x = x0; x < view.ni(); ++x)
00600 {
00601 vxl_uint_16 tempbuf[3];
00602 for (unsigned p = 0; p < ncomponents_; ++p)
00603 tempbuf[p] = (*pb)(x,y,p);
00604 #if VXL_LITTLE_ENDIAN
00605 ConvertHostToMSB(tempbuf, ncomponents_);
00606 #endif
00607 vs_->write(tempbuf, bytes_per_pixel);
00608 }
00609 byte_start += byte_width;
00610 }
00611 }
00612 else {
00613 vcl_cerr << "ERROR: pgm: writing rawbits format with > 16bit samples\n";
00614 return false;
00615 }
00616 }
00617 else if (magic_ == 4)
00618 {
00619 int byte_width = (ni_+7)/8;
00620
00621 assert(bb!=0);
00622 for (unsigned y = 0; y < view.nj(); ++y)
00623 {
00624 vil_streampos byte_start = start_of_data_ + (y0+y) * byte_width + x0/8;
00625 int s = x0&7;
00626 unsigned char a = 0;
00627 if (s)
00628 {
00629 vs_->read(&a, 1L);
00630 vs_->seek(byte_start);
00631 a &= ((1<<s)-1)<<(8-s);
00632 }
00633 for (unsigned x = 0; x < view.ni(); ++x)
00634 {
00635 if ((*bb)(x,y)) a |= 1<<(7-s);
00636 if (s >= 7) { vs_->write(&a, 1L); ++byte_start; s = 0; a = 0; }
00637 else ++s;
00638 }
00639 if (s)
00640 {
00641 if (x0+view.ni() < ni_)
00642 {
00643 vs_->seek(byte_start);
00644 unsigned char c; vs_->read(&c, 1L);
00645 vs_->seek(byte_start);
00646 c &= ((1<<(8-s))-1);
00647 a |= c;
00648 }
00649 vs_->write(&a, 1L);
00650 }
00651 }
00652 }
00653 else
00654 {
00655 if (x0 > 0 || y0 > 0 || view.ni() < ni_ || view.nj() < nj_)
00656 return false;
00657 vs_->seek(start_of_data_);
00658 for (unsigned y = 0; y < view.nj(); ++y)
00659 for (unsigned x = 0; x < view.ni(); ++x)
00660 for (unsigned p = 0; p < ncomponents_; ++p)
00661 {
00662 if (bits_per_component_ <= 1) (*vs_) << (*bb)(x,y,p);
00663 else if (bits_per_component_ <= 8) (*vs_) << (*ob)(x,y,p);
00664 else if (bits_per_component_ <= 16) (*vs_) << (*pb)(x,y,p);
00665 else (*vs_) << (*qb)(x,y,p);
00666 }
00667 }
00668
00669 return true;
00670 }