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

panda/src/pnmimagetypes/pnmFileTypeAlias.cxx

Go to the documentation of this file.
00001 // Filename: pnmFileTypeAlias.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 "pnmFileTypeAlias.h"
00020 #include "config_pnmimagetypes.h"
00021 
00022 #include <pnmFileTypeRegistry.h>
00023 #include <bamReader.h>
00024 
00025 // Since Alias image files don't have a magic number, we'll make a
00026 // little sanity check on the size of the image.  If either the width
00027 // or height is larger than this, it must be bogus.
00028 #define INSANE_SIZE 20000
00029 
00030 static const char * const extensions_alias[] = {
00031   "pix", "als"
00032 };
00033 static const int num_extensions_alias = sizeof(extensions_alias) / sizeof(const char *);
00034 
00035 TypeHandle PNMFileTypeAlias::_type_handle;
00036 
00037 ////////////////////////////////////////////////////////////////////
00038 //     Function: PNMFileTypeAlias::Constructor
00039 //       Access: Public
00040 //  Description:
00041 ////////////////////////////////////////////////////////////////////
00042 PNMFileTypeAlias::
00043 PNMFileTypeAlias() {
00044 }
00045 
00046 ////////////////////////////////////////////////////////////////////
00047 //     Function: PNMFileTypeAlias::get_name
00048 //       Access: Public, Virtual
00049 //  Description: Returns a few words describing the file type.
00050 ////////////////////////////////////////////////////////////////////
00051 string PNMFileTypeAlias::
00052 get_name() const {
00053   return "Alias";
00054 }
00055 
00056 ////////////////////////////////////////////////////////////////////
00057 //     Function: PNMFileTypeAlias::get_num_extensions
00058 //       Access: Public, Virtual
00059 //  Description: Returns the number of different possible filename
00060 //               extensions associated with this particular file type.
00061 ////////////////////////////////////////////////////////////////////
00062 int PNMFileTypeAlias::
00063 get_num_extensions() const {
00064   return num_extensions_alias;
00065 }
00066 
00067 ////////////////////////////////////////////////////////////////////
00068 //     Function: PNMFileTypeAlias::get_extension
00069 //       Access: Public, Virtual
00070 //  Description: Returns the nth possible filename extension
00071 //               associated with this particular file type, without a
00072 //               leading dot.
00073 ////////////////////////////////////////////////////////////////////
00074 string PNMFileTypeAlias::
00075 get_extension(int n) const {
00076   nassertr(n >= 0 && n < num_extensions_alias, string());
00077   return extensions_alias[n];
00078 }
00079 
00080 ////////////////////////////////////////////////////////////////////
00081 //     Function: PNMFileTypeAlias::get_suggested_extension
00082 //       Access: Public, Virtual
00083 //  Description: Returns a suitable filename extension (without a
00084 //               leading dot) to suggest for files of this type, or
00085 //               empty string if no suggestions are available.
00086 ////////////////////////////////////////////////////////////////////
00087 string PNMFileTypeAlias::
00088 get_suggested_extension() const {
00089   return "pix";
00090 }
00091 
00092 ////////////////////////////////////////////////////////////////////
00093 //     Function: PNMFileTypeAlias::make_reader
00094 //       Access: Public, Virtual
00095 //  Description: Allocates and returns a new PNMReader suitable for
00096 //               reading from this file type, if possible.  If reading
00097 //               from this file type is not supported, returns NULL.
00098 ////////////////////////////////////////////////////////////////////
00099 PNMReader *PNMFileTypeAlias::
00100 make_reader(istream *file, bool owns_file, const string &magic_number) {
00101   init_pnm();
00102   return new Reader(this, file, owns_file, magic_number);
00103 }
00104 
00105 ////////////////////////////////////////////////////////////////////
00106 //     Function: PNMFileTypeAlias::make_writer
00107 //       Access: Public, Virtual
00108 //  Description: Allocates and returns a new PNMWriter suitable for
00109 //               reading from this file type, if possible.  If writing
00110 //               files of this type is not supported, returns NULL.
00111 ////////////////////////////////////////////////////////////////////
00112 PNMWriter *PNMFileTypeAlias::
00113 make_writer(ostream *file, bool owns_file) {
00114   init_pnm();
00115   return new Writer(this, file, owns_file);
00116 }
00117 
00118 
00119 
00120 inline unsigned short
00121 read_ushort(istream *file) {
00122   unsigned short x;
00123   return pm_readbigshort(file, (short *)&x)==0 ? x : 0;
00124 }
00125 
00126 inline unsigned char
00127 read_uchar_ALIAS(istream *file) {
00128   int x;
00129   x = file->get();
00130   return (x!=EOF) ? (unsigned char)x : 0;
00131 }
00132 
00133 inline void
00134 write_ushort(ostream *file, unsigned short x) {
00135   pm_writebigshort(file, (short)x);
00136 }
00137 
00138 inline void
00139 write_uchar_ALIAS(ostream *file, unsigned char x) {
00140   file->put(x);
00141 }
00142 
00143 ////////////////////////////////////////////////////////////////////
00144 //     Function: PNMFileTypeAlias::Reader::Constructor
00145 //       Access: Public
00146 //  Description:
00147 ////////////////////////////////////////////////////////////////////
00148 PNMFileTypeAlias::Reader::
00149 Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) :
00150   PNMReader(type, file, owns_file)
00151 {
00152   if (!read_magic_number(_file, magic_number, 4)) {
00153     // Although Alias files have no magic number, they do have a
00154     // number of ushorts at the beginning.  If these aren't present,
00155     // we have a problem.
00156     if (pnmimage_alias_cat.is_debug()) {
00157       pnmimage_alias_cat.debug()
00158         << "Alias image file appears to be empty.\n";
00159     }
00160     _is_valid = false;
00161     return;
00162   }
00163 
00164   _x_size =
00165     ((unsigned char)magic_number[0] << 8) |
00166     ((unsigned char)magic_number[1]);
00167   _y_size =
00168     ((unsigned char)magic_number[2] << 8) |
00169     ((unsigned char)magic_number[3]);
00170 
00171   if (_x_size == 0 || _y_size == 0 ||
00172       _x_size > INSANE_SIZE || _y_size > INSANE_SIZE) {
00173     _is_valid = false;
00174     pnmimage_alias_cat.debug()
00175       << "File is not a valid Alias image.\n";
00176     return;
00177   }
00178 
00179   read_ushort(_file);
00180   read_ushort(_file);
00181 
00182   int bpp = read_ushort(_file);
00183 
00184   switch (bpp) {
00185   case 8:
00186     _num_channels = 1;
00187     break;
00188 
00189   case 24:
00190     _num_channels = 3;
00191     break;
00192 
00193   default:
00194     _is_valid = false;
00195     return;
00196   }
00197 
00198   _maxval = 255;
00199 
00200   if (pnmimage_alias_cat.is_debug()) {
00201     pnmimage_alias_cat.debug()
00202       << "Reading Alias " << *this << "\n";
00203   }
00204 }
00205 
00206 
00207 ////////////////////////////////////////////////////////////////////
00208 //     Function: PNMFileTypeAlias::Reader::supports_read_row
00209 //       Access: Public, Virtual
00210 //  Description: Returns true if this particular PNMReader supports a
00211 //               streaming interface to reading the data: that is, it
00212 //               is capable of returning the data one row at a time,
00213 //               via repeated calls to read_row().  Returns false if
00214 //               the only way to read from this file is all at once,
00215 //               via read_data().
00216 ////////////////////////////////////////////////////////////////////
00217 bool PNMFileTypeAlias::Reader::
00218 supports_read_row() const {
00219   return true;
00220 }
00221 
00222 ////////////////////////////////////////////////////////////////////
00223 //     Function: PNMFileTypeAlias::Reader::read_row
00224 //       Access: Public, Virtual
00225 //  Description: If supports_read_row(), above, returns true, this
00226 //               function may be called repeatedly to read the image,
00227 //               one horizontal row at a time, beginning from the top.
00228 //               Returns true if the row is successfully read, false
00229 //               if there is an error or end of file.
00230 ////////////////////////////////////////////////////////////////////
00231 bool PNMFileTypeAlias::Reader::
00232 read_row(xel *row_data, xelval *) {
00233   if (!is_valid()) {
00234     return false;
00235   }
00236 
00237   int x;
00238   int num;
00239   unsigned char red, grn, blu;
00240 
00241   x = 0;
00242   while (x < _x_size) {
00243     num = read_uchar_ALIAS(_file);
00244     if (num==0 || x+num > _x_size) {
00245       return false;
00246     }
00247     blu = read_uchar_ALIAS(_file);
00248 
00249     if (get_color_type() == PNMImageHeader::CT_color) {
00250       grn = read_uchar_ALIAS(_file);
00251       red = read_uchar_ALIAS(_file);
00252       while (num>0) {
00253         PPM_ASSIGN(row_data[x], red, grn, blu);
00254         x++;
00255         num--;
00256       }
00257     } else {
00258       while (num>0) {
00259         PPM_PUTB(row_data[x], blu);
00260         x++;
00261         num--;
00262       }
00263     }
00264   }
00265 
00266   return true;
00267 }
00268 
00269 static unsigned char last_red = 0, last_blu = 0, last_grn = 0;
00270 static int num_count = 0;
00271 
00272 static void
00273 flush_color(ostream *file) {
00274   if (num_count>0) {
00275     write_uchar_ALIAS(file, num_count);
00276     write_uchar_ALIAS(file, last_blu);
00277     write_uchar_ALIAS(file, last_grn);
00278     write_uchar_ALIAS(file, last_red);
00279     num_count = 0;
00280   }
00281 }
00282 
00283 static void
00284 write_color(ostream *file,
00285             unsigned char red, unsigned char blu, unsigned char grn) {
00286   if (red==last_red && blu==last_blu && grn==last_grn && num_count<0377) {
00287     num_count++;
00288   } else {
00289     flush_color(file);
00290     last_red = red;
00291     last_grn = grn;
00292     last_blu = blu;
00293     num_count = 1;
00294   }
00295 }
00296 
00297 
00298 ////////////////////////////////////////////////////////////////////
00299 //     Function: PNMFileTypeAlias::Writer::Constructor
00300 //       Access: Public
00301 //  Description:
00302 ////////////////////////////////////////////////////////////////////
00303 PNMFileTypeAlias::Writer::
00304 Writer(PNMFileType *type, ostream *file, bool owns_file) :
00305   PNMWriter(type, file, owns_file)
00306 {
00307 }
00308 
00309 ////////////////////////////////////////////////////////////////////
00310 //     Function: PNMFileTypeAlias::Writer::supports_write_row
00311 //       Access: Public, Virtual
00312 //  Description: Returns true if this particular PNMWriter supports a
00313 //               streaming interface to writing the data: that is, it
00314 //               is capable of writing the image one row at a time,
00315 //               via repeated calls to write_row().  Returns false if
00316 //               the only way to write from this file is all at once,
00317 //               via write_data().
00318 ////////////////////////////////////////////////////////////////////
00319 bool PNMFileTypeAlias::Writer::
00320 supports_write_row() const {
00321   return true;
00322 }
00323 
00324 ////////////////////////////////////////////////////////////////////
00325 //     Function: PNMFileTypeAlias::Writer::write_header
00326 //       Access: Public, Virtual
00327 //  Description: If supports_write_row(), above, returns true, this
00328 //               function may be called to write out the image header
00329 //               in preparation to writing out the image data one row
00330 //               at a time.  Returns true if the header is
00331 //               successfully written, false if there is an error.
00332 //
00333 //               It is the user's responsibility to fill in the header
00334 //               data via calls to set_x_size(), set_num_channels(),
00335 //               etc., or copy_header_from(), before calling
00336 //               write_header().
00337 ////////////////////////////////////////////////////////////////////
00338 bool PNMFileTypeAlias::Writer::
00339 write_header() {
00340   write_ushort(_file, _x_size);
00341   write_ushort(_file, _y_size);
00342 
00343   write_ushort(_file, 0);
00344   write_ushort(_file, 0);
00345 
00346   // We'll always write full-color Alias images, even if the source
00347   // was grayscale.  Many programs don't seem to understand grayscale
00348   // Alias images.
00349   write_ushort(_file, 24);
00350   return true;
00351 }
00352 
00353 ////////////////////////////////////////////////////////////////////
00354 //     Function: PNMFileTypeAlias::Writer::write_row
00355 //       Access: Public, Virtual
00356 //  Description: If supports_write_row(), above, returns true, this
00357 //               function may be called repeatedly to write the image,
00358 //               one horizontal row at a time, beginning from the top.
00359 //               Returns true if the row is successfully written,
00360 //               false if there is an error.
00361 //
00362 //               You must first call write_header() before writing the
00363 //               individual rows.  It is also important to delete the
00364 //               PNMWriter class after successfully writing the last
00365 //               row.  Failing to do this may result in some data not
00366 //               getting flushed!
00367 ////////////////////////////////////////////////////////////////////
00368 bool PNMFileTypeAlias::Writer::
00369 write_row(xel *row_data, xelval *) {
00370   int x;
00371   unsigned char red, grn, blu;
00372 
00373   bool grayscale = is_grayscale();
00374 
00375   for (x = 0; x < _x_size; x++) {
00376     if (grayscale) {
00377       red = grn = blu = (unsigned char)(255*PPM_GETB(row_data[x]) / _maxval);
00378     } else {
00379       red = (unsigned char)(255*PPM_GETR(row_data[x]) / _maxval);
00380       grn = (unsigned char)(255*PPM_GETG(row_data[x]) / _maxval);
00381       blu = (unsigned char)(255*PPM_GETB(row_data[x]) / _maxval);
00382     }
00383 
00384     write_color(_file, red, blu, grn);
00385   }
00386   flush_color(_file);
00387 
00388   return true;
00389 }
00390 
00391 
00392 
00393 ////////////////////////////////////////////////////////////////////
00394 //     Function: PNMFileTypeAlias::register_with_read_factory
00395 //       Access: Public, Static
00396 //  Description: Registers the current object as something that can be
00397 //               read from a Bam file.
00398 ////////////////////////////////////////////////////////////////////
00399 void PNMFileTypeAlias::
00400 register_with_read_factory() {
00401   BamReader::get_factory()->
00402     register_factory(get_class_type(), make_PNMFileTypeAlias);
00403 }
00404 
00405 ////////////////////////////////////////////////////////////////////
00406 //     Function: PNMFileTypeAlias::make_PNMFileTypeAlias
00407 //       Access: Protected, Static
00408 //  Description: This method is called by the BamReader when an object
00409 //               of this type is encountered in a Bam file; it should
00410 //               allocate and return a new object with all the data
00411 //               read.
00412 //
00413 //               In the case of the PNMFileType objects, since these
00414 //               objects are all shared, we just pull the object from
00415 //               the registry.
00416 ////////////////////////////////////////////////////////////////////
00417 TypedWritable *PNMFileTypeAlias::
00418 make_PNMFileTypeAlias(const FactoryParams &params) {
00419   return PNMFileTypeRegistry::get_ptr()->get_type_by_handle(get_class_type());
00420 }

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