00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008 #include "vil1_pnm.h"
00009
00010 #include <vcl_cassert.h>
00011 #include <vcl_vector.h>
00012 #include <vcl_iostream.h>
00013 #include <vcl_cstring.h>
00014
00015 #include <vil1/vil1_stream.h>
00016 #include <vil1/vil1_image_impl.h>
00017 #include <vil1/vil1_image.h>
00018 #include <vil1/vil1_property.h>
00019
00020 #include <vxl_config.h>
00021 #undef sprintf // This works around a bug in libintl.h
00022 #include <vcl_cstdio.h>
00023
00024 char const* vil1_pnm_format_tag = "pnm";
00025
00026 static inline bool iseol(int c)
00027 {
00028 return c == 10 || c == 13;
00029 }
00030
00031 static inline bool isws(int c)
00032 {
00033 return c == ' ' || c == '\t' || c == 10 || c == 13;
00034 }
00035
00036 vil1_image_impl* vil1_pnm_file_format::make_input_image(vil1_stream* vs)
00037 {
00038
00039 unsigned char buf[3];
00040 vs->read(buf, 3L);
00041 bool ok = ((buf[0] == 'P') &&
00042 iseol(buf[2]) &&
00043 (buf[1] >= '1' && buf[2] <= '6'));
00044 if (!ok)
00045 return 0;
00046
00047 return new vil1_pnm_generic_image(vs);
00048 }
00049
00050 vil1_image_impl* vil1_pnm_file_format::make_output_image(vil1_stream* vs, int planes,
00051 int width,
00052 int height,
00053 int components,
00054 int bits_per_component,
00055 vil1_component_format format)
00056 {
00057 return new vil1_pnm_generic_image(vs, planes, width, height, components, bits_per_component, format);
00058 }
00059
00060 char const* vil1_pnm_file_format::tag() const
00061 {
00062 return vil1_pnm_format_tag;
00063 }
00064
00065
00066
00067 vil1_pnm_generic_image::vil1_pnm_generic_image(vil1_stream* vs):
00068 vs_(vs)
00069 {
00070 vs_->ref();
00071 read_header();
00072 }
00073
00074 bool vil1_pnm_generic_image::get_property(char const *tag, void *prop) const
00075 {
00076 if (0==vcl_strcmp(tag, vil1_property_top_row_first))
00077 return prop ? (*(bool*)prop) = true : true;
00078
00079 if (0==vcl_strcmp(tag, vil1_property_left_first))
00080 return prop ? (*(bool*)prop) = true : true;
00081
00082 return false;
00083 }
00084
00085 char const* vil1_pnm_generic_image::file_format() const
00086 {
00087 return vil1_pnm_format_tag;
00088 }
00089
00090 vil1_pnm_generic_image::vil1_pnm_generic_image(vil1_stream* vs, int planes,
00091 int width,
00092 int height,
00093 int components,
00094 int bits_per_component,
00095 vil1_component_format ):
00096 vs_(vs)
00097 {
00098 vs_->ref();
00099 width_ = width;
00100 height_ = height;
00101
00102 components_ = components * planes;
00103 bits_per_component_ = bits_per_component;
00104
00105 if (components_ == 3) {
00106 magic_ = 6;
00107 } else if (components_ == 1) {
00108 if (bits_per_component_ == 1)
00109 magic_ = 4;
00110 else
00111 magic_ = 5;
00112 }
00113
00114 if (bits_per_component_ > 16) magic_ -= 3;
00115
00116 if (bits_per_component_ < 31)
00117 maxval_ = (1L<<bits_per_component_)-1;
00118 else
00119 maxval_ = 0x7FFFFFFF;
00120
00121 write_header();
00122 }
00123
00124 vil1_pnm_generic_image::~vil1_pnm_generic_image()
00125 {
00126
00127 vs_->unref();
00128 }
00129
00130
00131 static void SkipSpaces(vil1_stream* vs, char& temp)
00132 {
00133 while (isws(temp) || temp == '#')
00134 {
00135 if (temp == '#')
00136 while (!iseol(temp))
00137 if (1L > vs->read(&temp,1L)) return;
00138
00139 if (1L > vs->read(&temp,1L)) return;
00140 }
00141 }
00142
00143
00144 static int ReadInteger(vil1_stream* vs, char& temp)
00145 {
00146 int n = 0;
00147 while ((temp >= '0') && (temp <= '9'))
00148 {
00149 n *= 10; n += (temp - '0');
00150 if (1L > vs->read(&temp,1L)) return n;
00151 }
00152 return n;
00153 }
00154
00155 #if VXL_LITTLE_ENDIAN
00156
00157 static void ConvertMSBToHost( void* buf, int num_words )
00158 {
00159 unsigned char* ptr = (unsigned char*)buf;
00160 for ( int i=0; i < num_words; ++i ) {
00161 unsigned char t = *ptr;
00162 *ptr = *(ptr+1);
00163 *(ptr+1) = t;
00164 ptr += 2;
00165 }
00166 }
00167
00168
00169 static void ConvertHostToMSB( void* buf, int num_words )
00170 {
00171 unsigned char* ptr = (unsigned char*)buf;
00172 for ( int i=0; i < num_words; ++i ) {
00173 unsigned char t = *ptr;
00174 *ptr = *(ptr+1);
00175 *(ptr+1) = t;
00176 ptr += 2;
00177 }
00178 }
00179
00180 #else // VXL_BIG_ENDIAN: do nothing
00181 inline static void ConvertMSBToHost( void*, int ) {}
00182 inline static void ConvertHostToMSB( void*, int ) {}
00183 #endif
00184
00185
00186 bool vil1_pnm_generic_image::read_header()
00187 {
00188 char temp;
00189
00190
00191 vs_->seek(0L);
00192
00193 char buf[3];
00194 if (3L > vs_->read(buf, 3L)) return false;
00195 if (buf[0] != 'P') return false;
00196 if (!iseol(buf[2])) return false;
00197 magic_ = buf[1] - '0';
00198 if (magic_ < 1 || magic_ > 6) return false;
00199
00200
00201 vs_->read(&temp, 1L);
00202
00203
00204 SkipSpaces(vs_,temp);
00205
00206
00207 width_ = ReadInteger(vs_,temp);
00208
00209
00210 SkipSpaces(vs_,temp);
00211
00212
00213 height_ = ReadInteger(vs_,temp);
00214
00215
00216 if (magic_ == 1 || magic_ == 4)
00217 maxval_ = 1;
00218 else
00219 {
00220
00221 SkipSpaces(vs_,temp);
00222
00223
00224 maxval_ = ReadInteger(vs_,temp);
00225 }
00226
00227 start_of_data_ = vs_->tell() - 1L;
00228
00229
00230 if (isws(temp))
00231 ++start_of_data_;
00232
00233 components_ = ((magic_ == 3 || magic_ == 6) ? 3 : 1);
00234
00235 if (magic_ == 1 || magic_ == 4)
00236 bits_per_component_ = 1;
00237 else {
00238 if (maxval_ == 0) assert(!"indentation is everything");
00239 else if (maxval_ <= 0xFF) bits_per_component_ = 8;
00240 else if (maxval_ <= 0xFFFF) bits_per_component_ = 16;
00241 else if (maxval_ <= 0xFFFFFF) bits_per_component_ = 24;
00242 else if (maxval_ <= 0x7FFFFFFF) bits_per_component_ = 32;
00243 else assert(!"vil1_pnm_generic_image: maxval is too big");
00244 }
00245
00246 return true;
00247 }
00248
00249 bool vil1_pnm_generic_image::write_header()
00250 {
00251 vs_->seek(0L);
00252
00253 char buf[1024];
00254 vcl_sprintf(buf, "P%d\n#vil1 pnm image, #c=%u, bpc=%u\n%u %u\n",
00255 magic_, components_, bits_per_component_, width_, height_);
00256 vs_->write(buf, vcl_strlen(buf));
00257 if (magic_ != 1 && magic_ != 4)
00258 {
00259 vcl_sprintf(buf, "%lu\n", maxval_);
00260 vs_->write(buf, vcl_strlen(buf));
00261 }
00262 start_of_data_ = vs_->tell();
00263 return true;
00264 }
00265
00266 bool operator>>(vil1_stream& vs, int& a)
00267 {
00268 char c; vs.read(&c,1L);
00269 SkipSpaces(&vs,c);
00270 if (c < '0' || c > '9') return false;
00271 a = ReadInteger(&vs,c);
00272 return true;
00273 }
00274
00275 bool operator>>(vil1_stream& vs, unsigned char& a)
00276 {
00277 int b; vs >> b;
00278 a = static_cast<unsigned char>(b);
00279 return b >= 0 && b <= 0xff;
00280 }
00281
00282 bool operator>>(vil1_stream& vs, unsigned short& a)
00283 {
00284 int b; vs >> b;
00285 a = static_cast<unsigned short>(b);
00286 return b >= 0 && b <= 0xffff;
00287 }
00288
00289 bool operator>>(vil1_stream& vs, unsigned int& a)
00290 {
00291 int b; vs >> b;
00292 a = static_cast<unsigned int>(b);
00293 return b >= 0;
00294 }
00295
00296 bool vil1_pnm_generic_image::get_section(void* buf, int x0, int y0, int xs, int ys) const
00297 {
00298 unsigned char* ib = (unsigned char*) buf;
00299 unsigned short* jb = (unsigned short*) buf;
00300 unsigned int* kb = (unsigned int*) buf;
00301
00302 if (magic_ > 4)
00303 {
00304 int bytes_per_sample = (bits_per_component_+7)/8;
00305 int bytes_per_pixel = components_ * bytes_per_sample;
00306 int byte_start = start_of_data_ + (y0 * width_ + x0) * bytes_per_pixel;
00307 int byte_width = width_ * bytes_per_pixel;
00308 int byte_out_width = xs * bytes_per_pixel;
00309
00310 for (int y = 0; y < ys; ++y) {
00311 vs_->seek(byte_start + y * byte_width);
00312 vs_->read(ib + y * byte_out_width, byte_out_width);
00313 }
00314 if ( bytes_per_sample==2 && VXL_LITTLE_ENDIAN ) {
00315 ConvertMSBToHost( buf, xs*ys*components_ );
00316 } else if ( bytes_per_sample > 2 ) {
00317 vcl_cerr << "ERROR: pnm: reading rawbits format with > 16bit samples\n";
00318 return false;
00319 }
00320 }
00321 else if (magic_ == 4)
00322 {
00323 int byte_width = (width_+7)/8;
00324 int byte_out_width = (xs+7)/8;
00325
00326 for (int y = 0; y < ys; ++y) {
00327 vil1_streampos byte_start = start_of_data_ + (y0+y) * byte_width + x0/8;
00328 vs_->seek(byte_start);
00329 unsigned char a; vs_->read(&a, 1L);
00330 int s = x0&7;
00331 unsigned char b = 0;
00332 int t = 0;
00333 for (int x = 0; x < xs; ++x) {
00334 b |= static_cast<unsigned char>(((a>>(7-s))&1)<<(7-t));
00335 if (s >= 7) { vs_->read(&a, 1L); s = 0; }
00336 else ++s;
00337 if (t >= 7) { ib[y * byte_out_width + x/8] = b; b = 0; t = 0; }
00338 else ++t;
00339 }
00340 if (t) ib[y * byte_out_width + (xs-1)/8] = b;
00341 }
00342 }
00343 else
00344 {
00345 vs_->seek(start_of_data_);
00346
00347
00348 for (int t = 0; t < y0*width_*components_; ++t) { int a; (*vs_) >> a; }
00349 for (int y = 0; y < ys; ++y) {
00350
00351
00352 for (int t = 0; t < x0*components_; ++t) { int a; (*vs_) >> a; }
00353
00354
00355 if (bits_per_component_ <= 1) {
00356 --ib;
00357 for (int x=0,t=0; x<xs*components_; ++x,++t) {
00358 if ((t&=7)==0) *++ib=0; int a; (*vs_) >> a; if (a) *ib|=static_cast<unsigned char>(1<<(7-t)); }
00359 ++ib;
00360 }
00361 else if (bits_per_component_ <= 8)
00362 for (int x = 0; x < xs*components_; ++x) { unsigned char a; (*vs_) >> a; *(ib++)=a; }
00363 else if (bits_per_component_ <= 16)
00364 for (int x = 0; x < xs*components_; ++x) { unsigned short a; (*vs_) >> a; *(jb++)=a; }
00365 else
00366 for (int x = 0; x < xs*components_; ++x) { unsigned int a; (*vs_) >> a; *(kb++)=a; }
00367
00368
00369 for (int t = 0; t < (width_-x0-xs)*components_; ++t) { int a; (*vs_) >> a; }
00370 }
00371 }
00372
00373 return true;
00374 }
00375
00376 void operator<<(vil1_stream& vs, int a)
00377 {
00378 char buf[128]; vcl_sprintf(buf, " %d\n", a); vs.write(buf,vcl_strlen(buf));
00379 }
00380
00381 bool vil1_pnm_generic_image::put_section(void const* buf, int x0, int y0, int xs, int ys)
00382 {
00383 unsigned char const* ob = (unsigned char const*) buf;
00384 unsigned short const* pb = (unsigned short const*) buf;
00385 unsigned int const* qb = (unsigned int const*) buf;
00386
00387 if (magic_ > 4)
00388 {
00389 int bytes_per_sample = (bits_per_component_+7)/8;
00390 int bytes_per_pixel = components_ * bytes_per_sample;
00391 vil1_streampos byte_start = start_of_data_ + (y0 * width_ + x0) * bytes_per_pixel;
00392 int byte_width = width_ * bytes_per_pixel;
00393 int byte_out_width = xs * bytes_per_pixel;
00394
00395 if ( bytes_per_sample==1 || ( bytes_per_sample==2 && VXL_BIG_ENDIAN ) ) {
00396 for (int y = 0; y < ys; ++y) {
00397 vs_->seek(byte_start + y * byte_width);
00398 vs_->write(ob + y * byte_out_width, byte_out_width);
00399 }
00400 }
00401 else if ( bytes_per_sample==2 ) {
00402
00403
00404
00405 vcl_vector<unsigned char> tempbuf( byte_out_width );
00406 for (int y = 0; y < ys; ++y) {
00407 vs_->seek(byte_start + y * byte_width);
00408 vcl_memcpy( &tempbuf[0], ob + y * byte_out_width, byte_out_width );
00409 ConvertHostToMSB( &tempbuf[0], xs*components_ );
00410 vs_->write(&tempbuf[0], byte_out_width);
00411 }
00412 }
00413 else {
00414 vcl_cerr << "ERROR: pnm: writing rawbits format with > 16bit samples\n";
00415 return false;
00416 }
00417 }
00418 else if (magic_ == 4)
00419 {
00420 int byte_width = (width_+7)/8;
00421 int byte_out_width = (xs+7)/8;
00422
00423 for (int y = 0; y < ys; ++y)
00424 {
00425 vil1_streampos byte_start = start_of_data_ + (y0+y) * byte_width + x0/8;
00426 vs_->seek(byte_start);
00427 int s = x0&7;
00428 int t = 0;
00429 unsigned char a = 0, b = ob[y * byte_out_width];
00430 if (s) {
00431 vs_->read(&a, 1L);
00432 vs_->seek(byte_start);
00433 a &= static_cast<unsigned char>(((1<<s)-1)<<(8-s));
00434 }
00435 for (int x = 0; x < xs; ++x) {
00436 if (b&(1<<(7-t))) a |= static_cast<unsigned char>(1<<(7-s));
00437 if (t >= 7) { b = ob[y * byte_out_width + (x+1)/8]; t = 0; }
00438 else ++t;
00439 if (s >= 7) { vs_->write(&a, 1L); ++byte_start; s = 0; a = 0; }
00440 else ++s;
00441 }
00442 if (s) {
00443 if (x0+xs < width_) {
00444 vs_->seek(byte_start);
00445 unsigned char c; vs_->read(&c, 1L);
00446 vs_->seek(byte_start);
00447 c &= static_cast<unsigned char>((1<<(8-s))-1);
00448 a |= c;
00449 }
00450 vs_->write(&a, 1L);
00451 }
00452 }
00453 }
00454 else
00455 {
00456 if (x0 > 0 || y0 > 0 || xs < width_)
00457 return false;
00458 vs_->seek(start_of_data_);
00459 for (int y = 0; y < ys; ++y) {
00460 if (bits_per_component_ <= 1)
00461 for (int x = 0; x < xs*components_; ++x) { (*vs_) << ((ob[x/8]>>(7-(x&7)))&1); }
00462 else if (bits_per_component_ <= 8)
00463 for (int x = 0; x < xs*components_; ++x) { (*vs_) << ob[x]; }
00464 else if (bits_per_component_ <= 16)
00465 for (int x = 0; x < xs*components_; ++x) { (*vs_) << pb[x]; }
00466 else
00467 for (int x = 0; x < xs*components_; ++x) { (*vs_) << qb[x]; }
00468 ob += xs; pb += xs; qb += xs;
00469 }
00470 }
00471
00472 return true;
00473 }
00474
00475 vil1_image vil1_pnm_generic_image::get_plane(unsigned int plane) const
00476 {
00477 assert(plane == 0);
00478 return const_cast<vil1_pnm_generic_image*>(this);
00479 }