Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/pnmimagetypes/pnmFileTypeSoftImage.cxx

Go to the documentation of this file.
00001 // Filename: pnmFileTypeSoftImage.cxx
00002 // Created by:  drose (17Jun00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "pnmFileTypeSoftImage.h"
00020 #include "config_pnmimagetypes.h"
00021 
00022 #include "pnmFileTypeRegistry.h"
00023 #include "bamReader.h"
00024 
00025 static const float imageVersionNumber = 3.0;
00026 static const int imageCommentLength = 80;
00027 static const char imageComment[imageCommentLength+1] =
00028   "Written by pnmimage.";
00029 
00030 // Values to indicate compressed/uncompressed types
00031 #define UNCOMPRESSED 0x00
00032 #define MIXED_RUN_LENGTH 0x02
00033 
00034 // Bits to indicate channel type
00035 #define RGB_CHANNEL 0xe0
00036 #define ALPHA_CHANNEL 0x10
00037 
00038 // SoftImage magic number: high word, low word
00039 #define SOFTIMAGE_MAGIC1 0x5380
00040 #define SOFTIMAGE_MAGIC2 0xf634
00041 
00042 static const char * const extensions_softimage[] = {
00043   "pic", "soft"
00044 };
00045 static const int num_extensions_softimage = sizeof(extensions_softimage) / sizeof(const char *);
00046 
00047 TypeHandle PNMFileTypeSoftImage::_type_handle;
00048 
00049 inline float
00050 read_float(istream *file) {
00051   long l;
00052 
00053   if (pm_readbiglong(file, &l)==0) {
00054     return *(float *)&l;
00055   } else {
00056     return 0.0;
00057   }
00058 }
00059 
00060 inline unsigned short
00061 read_ushort_SI(istream *file) {
00062   unsigned short x;
00063   return pm_readbigshort(file, (short *)&x)==0 ? x : 0;
00064 }
00065 
00066 inline unsigned char
00067 read_uchar_SI(istream *file) {
00068   int x;
00069   x = file->get();
00070   return (x!=EOF) ? (unsigned char)x : 0;
00071 }
00072 
00073 inline void
00074 write_ushort_SI(ostream *file, unsigned short x) {
00075   pm_writebigshort(file, (short)x);
00076 }
00077 
00078 inline void
00079 write_uchar_SI(ostream *file, unsigned char x) {
00080   file->put(x);
00081 }
00082 
00083 inline void
00084 write_float(ostream *file, float x) {
00085   pm_writebiglong(file, *(long *)&x);
00086 }
00087 
00088 static int
00089 read_channel_pkt(istream *file,
00090                  int &chained, int &size, int &type, int &channel) {
00091   chained = read_uchar_SI(file);
00092   size = read_uchar_SI(file);
00093   type = read_uchar_SI(file);
00094   channel = read_uchar_SI(file);
00095 
00096   if (file->eof() || file->fail()) {
00097     return false;
00098   }
00099 
00100   if (size!=8) {
00101     pnmimage_soft_cat.error()
00102       << "Don't know how to interpret " << size << " bits per pixel!\n";
00103     return false;
00104   }
00105 
00106   return true;
00107 }
00108 
00109 static void
00110 read_rgb(xel *row_data, xelval *, istream *file, int x, int repeat) {
00111   xelval red, grn, blu;
00112   red = read_uchar_SI(file);
00113   grn = read_uchar_SI(file);
00114   blu = read_uchar_SI(file);
00115 
00116   while (repeat>0) {
00117     PPM_ASSIGN(row_data[x], red, grn, blu);
00118     x++;
00119     repeat--;
00120   }
00121 }
00122 
00123 static void
00124 read_alpha(xel *, xelval *alpha_data, istream *file, int x, int repeat) {
00125   xelval alpha = read_uchar_SI(file);
00126 
00127   while (repeat>0) {
00128     alpha_data[x] = alpha;
00129     x++;
00130     repeat--;
00131   }
00132 }
00133 
00134 static void
00135 read_rgba(xel *row_data, xelval *alpha_data, istream *file, int x, int repeat) {
00136   xelval red, grn, blu, alpha;
00137   red = read_uchar_SI(file);
00138   grn = read_uchar_SI(file);
00139   blu = read_uchar_SI(file);
00140   alpha = read_uchar_SI(file);
00141 
00142   while (repeat>0) {
00143     PPM_ASSIGN(row_data[x], red, grn, blu);
00144     alpha_data[x] = alpha;
00145     x++;
00146     repeat--;
00147   }
00148 }
00149 
00150 
00151 static int
00152 read_scanline(xel *row_data, xelval *alpha_data, int cols, istream *file,
00153               void (*read_data)(xel *row_data, xelval *alpha_data, istream *file,
00154                                 int x, int repeat),
00155               int ctype) {
00156   if (ctype==UNCOMPRESSED) {
00157     for (int x = 0; x<cols; x++) {
00158       read_data(row_data, alpha_data, file, x, 1);
00159     }
00160     return true;
00161   } else {
00162     int x;
00163     int num;
00164 
00165     x = 0;
00166     while (x < cols) {
00167       num = read_uchar_SI(file);
00168 
00169       if (num<128) {
00170         // Sequence of non-repeated values.
00171         num++;
00172         if (x+num > cols) {
00173           return false;
00174         }
00175         while (num>0) {
00176           read_data(row_data, alpha_data, file, x, 1);
00177           if (file->eof() || file->fail()) {
00178             return false;
00179           }
00180           x++;
00181           num--;
00182         }
00183       } else {
00184         // Sequence of repeated values.
00185         if (num==128) {
00186           num = read_ushort_SI(file);
00187         } else {
00188           num -= 127;
00189         }
00190         if (x+num > cols) {
00191           return false;
00192         }
00193         read_data(row_data, alpha_data, file, x, num);
00194         if (file->eof() || file->fail()) {
00195           return false;
00196         }
00197         x += num;
00198       }
00199     }
00200 
00201     return (x==cols);
00202   }
00203 }
00204 
00205 ////////////////////////////////////////////////////////////////////
00206 //     Function: PNMFileTypeSoftImage::Constructor
00207 //       Access: Public
00208 //  Description:
00209 ////////////////////////////////////////////////////////////////////
00210 PNMFileTypeSoftImage::
00211 PNMFileTypeSoftImage() {
00212 }
00213 
00214 ////////////////////////////////////////////////////////////////////
00215 //     Function: PNMFileTypeSoftImage::get_name
00216 //       Access: Public, Virtual
00217 //  Description: Returns a few words describing the file type.
00218 ////////////////////////////////////////////////////////////////////
00219 string PNMFileTypeSoftImage::
00220 get_name() const {
00221   return "SoftImage";
00222 }
00223 
00224 ////////////////////////////////////////////////////////////////////
00225 //     Function: PNMFileTypeSoftImage::get_num_extensions
00226 //       Access: Public, Virtual
00227 //  Description: Returns the number of different possible filename
00228 //               extensions_softimage associated with this particular file type.
00229 ////////////////////////////////////////////////////////////////////
00230 int PNMFileTypeSoftImage::
00231 get_num_extensions() const {
00232   return num_extensions_softimage;
00233 }
00234 
00235 ////////////////////////////////////////////////////////////////////
00236 //     Function: PNMFileTypeSoftImage::get_extension
00237 //       Access: Public, Virtual
00238 //  Description: Returns the nth possible filename extension
00239 //               associated with this particular file type, without a
00240 //               leading dot.
00241 ////////////////////////////////////////////////////////////////////
00242 string PNMFileTypeSoftImage::
00243 get_extension(int n) const {
00244   nassertr(n >= 0 && n < num_extensions_softimage, string());
00245   return extensions_softimage[n];
00246 }
00247 
00248 ////////////////////////////////////////////////////////////////////
00249 //     Function: PNMFileTypeSoftImage::get_suggested_extension
00250 //       Access: Public, Virtual
00251 //  Description: Returns a suitable filename extension (without a
00252 //               leading dot) to suggest for files of this type, or
00253 //               empty string if no suggestions are available.
00254 ////////////////////////////////////////////////////////////////////
00255 string PNMFileTypeSoftImage::
00256 get_suggested_extension() const {
00257   return "pic";
00258 }
00259 
00260 ////////////////////////////////////////////////////////////////////
00261 //     Function: PNMFileTypeSoftImage::has_magic_number
00262 //       Access: Public, Virtual
00263 //  Description: Returns true if this particular file type uses a
00264 //               magic number to identify it, false otherwise.
00265 ////////////////////////////////////////////////////////////////////
00266 bool PNMFileTypeSoftImage::
00267 has_magic_number() const {
00268   return true;
00269 }
00270 
00271 ////////////////////////////////////////////////////////////////////
00272 //     Function: PNMFileTypeSoftImage::matches_magic_number
00273 //       Access: Public, Virtual
00274 //  Description: Returns true if the indicated "magic number" byte
00275 //               stream (the initial few bytes read from the file)
00276 //               matches this particular file type, false otherwise.
00277 ////////////////////////////////////////////////////////////////////
00278 bool PNMFileTypeSoftImage::
00279 matches_magic_number(const string &magic_number) const {
00280   nassertr(magic_number.size() >= 2, false);
00281   int mn =
00282     ((unsigned char)magic_number[0] << 8) |
00283     ((unsigned char)magic_number[1]);
00284   return (mn == SOFTIMAGE_MAGIC1);
00285 }
00286 
00287 ////////////////////////////////////////////////////////////////////
00288 //     Function: PNMFileTypeSoftImage::make_reader
00289 //       Access: Public, Virtual
00290 //  Description: Allocates and returns a new PNMReader suitable for
00291 //               reading from this file type, if possible.  If reading
00292 //               from this file type is not supported, returns NULL.
00293 ////////////////////////////////////////////////////////////////////
00294 PNMReader *PNMFileTypeSoftImage::
00295 make_reader(istream *file, bool owns_file, const string &magic_number) {
00296   init_pnm();
00297   return new Reader(this, file, owns_file, magic_number);
00298 }
00299 
00300 ////////////////////////////////////////////////////////////////////
00301 //     Function: PNMFileTypeSoftImage::make_writer
00302 //       Access: Public, Virtual
00303 //  Description: Allocates and returns a new PNMWriter suitable for
00304 //               reading from this file type, if possible.  If writing
00305 //               files of this type is not supported, returns NULL.
00306 ////////////////////////////////////////////////////////////////////
00307 PNMWriter *PNMFileTypeSoftImage::
00308 make_writer(ostream *file, bool owns_file) {
00309   init_pnm();
00310   return new Writer(this, file, owns_file);
00311 }
00312 
00313 
00314 ////////////////////////////////////////////////////////////////////
00315 //     Function: PNMFileTypeSoftImage::Reader::Constructor
00316 //       Access: Public
00317 //  Description:
00318 ////////////////////////////////////////////////////////////////////
00319 PNMFileTypeSoftImage::Reader::
00320 Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) :
00321   PNMReader(type, file, owns_file)
00322 {
00323   if (!read_magic_number(_file, magic_number, 4)) {
00324     // No magic number, no image.
00325     if (pnmimage_soft_cat.is_debug()) {
00326       pnmimage_soft_cat.debug()
00327         << "SoftImage image file appears to be empty.\n";
00328     }
00329     _is_valid = false;
00330     return;
00331   }
00332 
00333   int magic1 =
00334     ((unsigned char)magic_number[0] << 8) |
00335     ((unsigned char)magic_number[1]);
00336   int magic2 =
00337     ((unsigned char)magic_number[2] << 8) |
00338     ((unsigned char)magic_number[3]);
00339 
00340   if (magic1 != SOFTIMAGE_MAGIC1 || magic2 != SOFTIMAGE_MAGIC2) {
00341     _is_valid = false;
00342     return;
00343   }
00344 
00345   // skip version number
00346   read_float(_file);
00347 
00348   // Skip comment
00349   _file->seekg(imageCommentLength, ios::cur);
00350 
00351   char pict_id[4];
00352   _file->read(pict_id, 4);
00353   if (_file->gcount() < 4) {
00354     _is_valid = false;
00355     return;
00356   }
00357 
00358   if (memcmp(pict_id, "PICT", 4)!=0) {
00359     _is_valid = false;
00360     return;
00361   }
00362 
00363   _x_size = read_ushort_SI(_file);
00364   _y_size = read_ushort_SI(_file);
00365 
00366   /* float ratio = */ read_float(_file);
00367   /* int fields = */ read_ushort_SI(_file);
00368   read_ushort_SI(_file);
00369 
00370   int chained, size, channel;
00371   if (!read_channel_pkt(_file, chained, size, rgb_ctype, channel)) {
00372     _is_valid = false;
00373     return;
00374   }
00375 
00376   soft_color = unknown;
00377 
00378   if (channel == (RGB_CHANNEL | ALPHA_CHANNEL)) {
00379     // Four components in the first part: RGBA.
00380     soft_color = rgba;
00381 
00382   } else if (channel == RGB_CHANNEL) {
00383     // Three components in the first part: RGB.
00384     soft_color = rgb;
00385 
00386     if (chained) {
00387       if (!read_channel_pkt(_file, chained, size, alpha_ctype, channel)) {
00388         _is_valid = false;
00389         return;
00390       }
00391 
00392       if (channel == ALPHA_CHANNEL) {
00393         // Alpha component in the second part: RGBA.
00394         soft_color = rgb_a;
00395       }
00396     }
00397   }
00398 
00399   switch (soft_color) {
00400   case rgb:
00401     _num_channels = 3;
00402     break;
00403 
00404   case rgba:
00405   case rgb_a:
00406     _num_channels = 4;
00407     break;
00408 
00409   default:
00410     pnmimage_soft_cat.error()
00411       << "Image is not RGB or RGBA!\n";
00412     _is_valid = false;
00413     return;
00414   }
00415 
00416   if (chained) {
00417     pnmimage_soft_cat.error()
00418       << "Unexpected additional channels in image file.\n";
00419     _is_valid = false;
00420     return;
00421   }
00422 
00423   _maxval = 255;
00424 
00425   if (pnmimage_soft_cat.is_debug()) {
00426     pnmimage_soft_cat.debug()
00427       << "Reading SoftImage " << *this << "\n";
00428   }
00429 }
00430 
00431 
00432 ////////////////////////////////////////////////////////////////////
00433 //     Function: PNMFileTypeSoftImage::Reader::supports_read_row
00434 //       Access: Public, Virtual
00435 //  Description: Returns true if this particular PNMReader supports a
00436 //               streaming interface to reading the data: that is, it
00437 //               is capable of returning the data one row at a time,
00438 //               via repeated calls to read_row().  Returns false if
00439 //               the only way to read from this file is all at once,
00440 //               via read_data().
00441 ////////////////////////////////////////////////////////////////////
00442 bool PNMFileTypeSoftImage::Reader::
00443 supports_read_row() const {
00444   return true;
00445 }
00446 
00447 ////////////////////////////////////////////////////////////////////
00448 //     Function: PNMFileTypeSoftImage::Reader::read_row
00449 //       Access: Public, Virtual
00450 //  Description: If supports_read_row(), above, returns true, this
00451 //               function may be called repeatedly to read the image,
00452 //               one horizontal row at a time, beginning from the top.
00453 //               Returns true if the row is successfully read, false
00454 //               if there is an error or end of file.
00455 ////////////////////////////////////////////////////////////////////
00456 bool PNMFileTypeSoftImage::Reader::
00457 read_row(xel *row_data, xelval *alpha_data) {
00458   if (!is_valid()) {
00459     return false;
00460   }
00461   switch (soft_color) {
00462   case rgb:
00463     if (!read_scanline(row_data, alpha_data, _x_size, _file,
00464                        read_rgb, rgb_ctype)) {
00465       return false;
00466     }
00467     break;
00468 
00469   case rgba:
00470     if (!read_scanline(row_data, alpha_data, _x_size, _file,
00471                        read_rgba, rgb_ctype)) {
00472       return false;
00473     }
00474     break;
00475 
00476   case rgb_a:
00477     if (!read_scanline(row_data, alpha_data, _x_size, _file,
00478                        read_rgb, rgb_ctype)) {
00479       return false;
00480     }
00481     if (!read_scanline(row_data, alpha_data, _x_size, _file,
00482                        read_alpha, alpha_ctype)) {
00483       return false;
00484     }
00485     break;
00486 
00487   default:
00488     break;
00489   }
00490 
00491   return true;
00492 }
00493 
00494 
00495 static void
00496 write_channel_pkt(ostream *file,
00497                  int chained, int size, int type, int channel) {
00498   write_uchar_SI(file, chained);
00499   write_uchar_SI(file, size);
00500   write_uchar_SI(file, type);
00501   write_uchar_SI(file, channel);
00502 }
00503 
00504 static void
00505 write_rgb(xel *row_data, xelval *, ostream *file, int x) {
00506   write_uchar_SI(file, PPM_GETR(row_data[x]));
00507   write_uchar_SI(file, PPM_GETG(row_data[x]));
00508   write_uchar_SI(file, PPM_GETB(row_data[x]));
00509 }
00510 
00511 static int
00512 compare_rgb(xel *row_data, xelval *, int x1, int x2) {
00513   return PPM_EQUAL(row_data[x1], row_data[x2]);
00514 }
00515 
00516 static void
00517 write_gray(xel *row_data, xelval *, ostream *file, int x) {
00518   write_uchar_SI(file, PPM_GETB(row_data[x]));
00519   write_uchar_SI(file, PPM_GETB(row_data[x]));
00520   write_uchar_SI(file, PPM_GETB(row_data[x]));
00521 }
00522 
00523 static int
00524 compare_gray(xel *row_data, xelval *, int x1, int x2) {
00525   return (PPM_GETB(row_data[x1])==PPM_GETB(row_data[x2]));
00526 }
00527 
00528 static void
00529 write_alpha(xel *, xelval *alpha_data, ostream *file, int x) {
00530   write_uchar_SI(file, alpha_data[x]);
00531 }
00532 
00533 static int
00534 compare_alpha(xel *, xelval *alpha_data, int x1, int x2) {
00535   return (alpha_data[x1]==alpha_data[x2]);
00536 }
00537 
00538 static void
00539 write_diff(xel *row_data, xelval *alpha_data, ostream *file,
00540            void (*write_data)(xel *row_data, xelval *alpha_data, ostream *file,
00541                               int x),
00542            int tox, int length) {
00543   if (length>0) {
00544     nassertv(length<=128);
00545 
00546     write_uchar_SI(file, length-1);
00547     while (length>0) {
00548       length--;
00549       write_data(row_data, alpha_data, file, tox-length);
00550     }
00551   }
00552 }
00553 
00554 static void
00555 write_same(xel *row_data, xelval *alpha_data, ostream *file,
00556            void (*write_data)(xel *row_data, xelval *alpha_data, ostream *file,
00557                               int x),
00558            int tox, int length) {
00559   if (length==1) {
00560     write_diff(row_data, alpha_data, file, write_data, tox, length);
00561 
00562   } else if (length>0) {
00563     if (length<128) {
00564       write_uchar_SI(file, length+127);
00565     } else {
00566       write_uchar_SI(file, 128);
00567       write_ushort_SI(file, length);
00568     }
00569     write_data(row_data, alpha_data, file, tox);
00570   }
00571 }
00572 
00573 
00574 static void
00575 write_scanline(xel *row_data, xelval *alpha_data, int cols, ostream *file,
00576                int (*compare_data)(xel *row_data, xelval *alpha_data,
00577                                    int x1, int x2),
00578                void (*write_data)(xel *row_data, xelval *alpha_data,
00579                                   ostream *file, int x)) {
00580   int run_length = 0;
00581 
00582   int x = 0;
00583   int same = true;
00584 
00585   // Go through each value in the scanline, from beginning to end, looking
00586   // for runs of identical values.
00587   while (x < cols) {
00588 
00589     if (same) {
00590 
00591       // We have been scanning past a run of identical values.  In this case,
00592       // the run is the sequence of values from x-run_length to x-1.
00593 
00594       if (!compare_data(row_data, alpha_data, x, x-run_length)) {
00595         // Oops, the end of a run.
00596 
00597         if (run_length <= 1) {
00598           // If run_length is only 1, no big deal--this is actually the
00599           // beginning of a different-valued run.
00600 
00601           same = false;
00602 
00603         } else {
00604           // Write out the old run and begin a new one.  We'll be optimistic
00605           // and hope the new run will also represent a sequence of identical
00606           // values (until we find otherwise).
00607 
00608           write_same(row_data, alpha_data, file, write_data, x-1, run_length);
00609           same = true;
00610           run_length = 0;
00611         }
00612       }
00613 
00614     } else {   // !same
00615 
00616       // We have been scanning past a run of different values.  In this case,
00617       // the run is the sequence of values from x-run_length to x-1.
00618 
00619       if (run_length>128) {
00620         // We can't have different runs of more than 128 characters.  Close
00621         // off the old run.
00622 
00623         int excess = run_length - 128;
00624         write_diff(row_data, alpha_data, file, write_data, x-excess-1, 128);
00625         run_length = excess;
00626 
00627       } else if (run_length > 2 &&
00628                  compare_data(row_data, alpha_data, x, x-1) &&
00629                  compare_data(row_data, alpha_data, x, x-2)) {
00630 
00631         // If the last three values have been the same, then it's time to
00632         // begin a new run of similar values.  Close off the old run.
00633 
00634         write_diff(row_data, alpha_data, file, write_data, x-3, run_length-2);
00635         same = true;
00636         run_length = 2;
00637       }
00638     }
00639 
00640     x++;
00641     run_length++;
00642   }
00643 
00644   // We made it all the way to the end.  Flush out the last run.
00645 
00646   if (run_length>0) {
00647     if (same) {
00648       write_same(row_data, alpha_data, file, write_data, cols-1, run_length);
00649     } else {
00650 
00651       // Mighty unlikely, but we might have just run over the
00652       // 128-pixel limit.
00653       if (run_length>128) {
00654         int excess = run_length - 128;
00655         write_diff(row_data, alpha_data, file, write_data, cols-excess-1, 128);
00656         run_length = excess;
00657       }
00658 
00659       write_diff(row_data, alpha_data, file, write_data, cols-1, run_length);
00660     }
00661   }
00662 }
00663 
00664 ////////////////////////////////////////////////////////////////////
00665 //     Function: PNMFileTypeSoftImage::Writer::Constructor
00666 //       Access: Public
00667 //  Description:
00668 ////////////////////////////////////////////////////////////////////
00669 PNMFileTypeSoftImage::Writer::
00670 Writer(PNMFileType *type, ostream *file, bool owns_file) :
00671   PNMWriter(type, file, owns_file)
00672 {
00673 }
00674 
00675 ////////////////////////////////////////////////////////////////////
00676 //     Function: PNMFileTypeSoftImage::Writer::supports_write_row
00677 //       Access: Public, Virtual
00678 //  Description: Returns true if this particular PNMWriter supports a
00679 //               streaming interface to writing the data: that is, it
00680 //               is capable of writing the image one row at a time,
00681 //               via repeated calls to write_row().  Returns false if
00682 //               the only way to write from this file is all at once,
00683 //               via write_data().
00684 ////////////////////////////////////////////////////////////////////
00685 bool PNMFileTypeSoftImage::Writer::
00686 supports_write_row() const {
00687   return true;
00688 }
00689 
00690 ////////////////////////////////////////////////////////////////////
00691 //     Function: PNMFileTypeSoftImage::Writer::write_header
00692 //       Access: Public, Virtual
00693 //  Description: If supports_write_row(), above, returns true, this
00694 //               function may be called to write out the image header
00695 //               in preparation to writing out the image data one row
00696 //               at a time.  Returns true if the header is
00697 //               successfully written, false if there is an error.
00698 //
00699 //               It is the user's responsibility to fill in the header
00700 //               data via calls to set_x_size(), set_num_channels(),
00701 //               etc., or copy_header_from(), before calling
00702 //               write_header().
00703 ////////////////////////////////////////////////////////////////////
00704 bool PNMFileTypeSoftImage::Writer::
00705 write_header() {
00706   write_ushort_SI(_file, SOFTIMAGE_MAGIC1);
00707   write_ushort_SI(_file, SOFTIMAGE_MAGIC2);
00708   write_float(_file, imageVersionNumber);
00709 
00710   _file->write(imageComment, imageCommentLength);
00711   _file->write("PICT", 4);
00712 
00713   write_ushort_SI(_file, _x_size);
00714   write_ushort_SI(_file, _y_size);
00715 
00716   write_float(_file, 1.0);    // pixel aspect ratio; we don't know.
00717   write_ushort_SI(_file, 3);     // fields value; we don't really know either.
00718   write_ushort_SI(_file, 0);     // padding
00719 
00720   // There doesn't seem to be a variation on SoftImage image formats for
00721   // grayscale images.  We'll write out grayscale as a 3-channel image.
00722 
00723   if (has_alpha()) {
00724     write_channel_pkt(_file, 1, 8, MIXED_RUN_LENGTH, RGB_CHANNEL);
00725     write_channel_pkt(_file, 0, 8, MIXED_RUN_LENGTH, ALPHA_CHANNEL);
00726   } else {
00727     write_channel_pkt(_file, 0, 8, MIXED_RUN_LENGTH, RGB_CHANNEL);
00728   }
00729 
00730   return true;
00731 }
00732 
00733 ////////////////////////////////////////////////////////////////////
00734 //     Function: PNMFileTypeSoftImage::Writer::write_row
00735 //       Access: Public, Virtual
00736 //  Description: If supports_write_row(), above, returns true, this
00737 //               function may be called repeatedly to write the image,
00738 //               one horizontal row at a time, beginning from the top.
00739 //               Returns true if the row is successfully written,
00740 //               false if there is an error.
00741 //
00742 //               You must first call write_header() before writing the
00743 //               individual rows.  It is also important to delete the
00744 //               PNMWriter class after successfully writing the last
00745 //               row.  Failing to do this may result in some data not
00746 //               getting flushed!
00747 ////////////////////////////////////////////////////////////////////
00748 bool PNMFileTypeSoftImage::Writer::
00749 write_row(xel *row_data, xelval *alpha_data) {
00750   if (is_grayscale()) {
00751     write_scanline(row_data, alpha_data, _x_size, _file, compare_gray, write_gray);
00752 
00753   } else {
00754     write_scanline(row_data, alpha_data, _x_size, _file, compare_rgb, write_rgb);
00755   }
00756 
00757   if (has_alpha()) {
00758     write_scanline(row_data, alpha_data, _x_size, _file, compare_alpha, write_alpha);
00759   }
00760 
00761   return !_file->fail();
00762 }
00763 
00764 
00765 
00766 ////////////////////////////////////////////////////////////////////
00767 //     Function: PNMFileTypeSoftImage::register_with_read_factory
00768 //       Access: Public, Static
00769 //  Description: Registers the current object as something that can be
00770 //               read from a Bam file.
00771 ////////////////////////////////////////////////////////////////////
00772 void PNMFileTypeSoftImage::
00773 register_with_read_factory() {
00774   BamReader::get_factory()->
00775     register_factory(get_class_type(), make_PNMFileTypeSoftImage);
00776 }
00777 
00778 ////////////////////////////////////////////////////////////////////
00779 //     Function: PNMFileTypeSoftImage::make_PNMFileTypeSoftImage
00780 //       Access: Protected, Static
00781 //  Description: This method is called by the BamReader when an object
00782 //               of this type is encountered in a Bam file; it should
00783 //               allocate and return a new object with all the data
00784 //               read.
00785 //
00786 //               In the case of the PNMFileType objects, since these
00787 //               objects are all shared, we just pull the object from
00788 //               the registry.
00789 ////////////////////////////////////////////////////////////////////
00790 TypedWritable *PNMFileTypeSoftImage::
00791 make_PNMFileTypeSoftImage(const FactoryParams &params) {
00792   return PNMFileTypeRegistry::get_ptr()->get_type_by_handle(get_class_type());
00793 }

Generated on Fri May 2 00:43:22 2003 for Panda by doxygen1.3