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

panda/src/pnmimage/pnmImageHeader.cxx

Go to the documentation of this file.
00001 // Filename: pnmImageHeader.cxx
00002 // Created by:  drose (14Jun00)
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 "pnmImageHeader.h"
00020 #include "pnmFileTypeRegistry.h"
00021 #include "pnmFileType.h"
00022 #include "pnmReader.h"
00023 #include "config_pnmimage.h"
00024 #include "config_express.h"
00025 #include "virtualFileSystem.h"
00026 
00027 ////////////////////////////////////////////////////////////////////
00028 //     Function: PNMImageHeader::read_header
00029 //       Access: Public
00030 //  Description: Opens up the image file and tries to read its header
00031 //               information to determine its size, number of
00032 //               channels, etc.  If successful, updates the header
00033 //               information and returns true; otherwise, returns
00034 //               false.
00035 ////////////////////////////////////////////////////////////////////
00036 bool PNMImageHeader::
00037 read_header(const Filename &filename, PNMFileType *type) {
00038   PNMReader *reader = make_reader(filename, type);
00039   if (reader != (PNMReader *)NULL) {
00040     (*this) = (*reader);
00041     _type = reader->get_type();
00042     delete reader;
00043     return true;
00044   }
00045 
00046   return false;
00047 }
00048 
00049 ////////////////////////////////////////////////////////////////////
00050 //     Function: PNMImageHeader::make_reader
00051 //       Access: Public
00052 //  Description: Returns a newly-allocated PNMReader of the suitable
00053 //               type for reading from the indicated image filename,
00054 //               or NULL if the filename cannot be read for some
00055 //               reason.  The filename "-" always stands for standard
00056 //               input.  If type is specified, it is a suggestion for
00057 //               the file type to use.
00058 //
00059 //               The PNMReader should be deleted when it is no longer
00060 //               needed.
00061 ////////////////////////////////////////////////////////////////////
00062 PNMReader *PNMImageHeader::
00063 make_reader(const Filename &filename, PNMFileType *type) const {
00064   if (pnmimage_cat.is_debug()) {
00065     pnmimage_cat.debug()
00066       << "Reading image from " << filename << "\n";
00067   }
00068   bool owns_file = false;
00069   istream *file = (istream *)NULL;
00070 
00071   if (filename == "-") {
00072     owns_file = false;
00073     file = &cin;
00074 
00075     if (pnmimage_cat.is_debug()) {
00076       pnmimage_cat.debug()
00077         << "(reading standard input)\n";
00078     }
00079 
00080   } else {
00081     if (use_vfs) {
00082       VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00083       owns_file = true;
00084       file = vfs->open_read_file(filename);
00085 
00086     } else {
00087       ifstream *new_istream = new ifstream;
00088       Filename actual_name = Filename::binary_filename(filename);
00089       if (!actual_name.open_read(*new_istream)) {
00090         delete new_istream;
00091 
00092       } else {
00093         owns_file = true;
00094         file = new_istream;
00095       }
00096     }
00097   }
00098 
00099   if (file == (istream *)NULL) {
00100     if (pnmimage_cat.is_debug()) {
00101       pnmimage_cat.debug()
00102         << "Unable to open file.\n";
00103     }
00104     return NULL;
00105   }
00106 
00107   return make_reader(file, owns_file, filename, string(), type);
00108 }
00109 
00110 
00111 ////////////////////////////////////////////////////////////////////
00112 //     Function: PNMImageHeader::make_reader
00113 //       Access: Public
00114 //  Description: Returns a newly-allocated PNMReader of the suitable
00115 //               type for reading from the already-opened image file,
00116 //               or NULL if the file cannot be read for some reason.
00117 //
00118 //               owns_file should be set true if the PNMReader is to
00119 //               be considered the owner of the stream pointer (in
00120 //               which case the stream will be deleted on completion,
00121 //               whether successful or not), or false if it should not
00122 //               delete it.
00123 //
00124 //               The filename parameter is optional here, since the
00125 //               file has already been opened; it is only used to
00126 //               examine the extension and attempt to guess the file
00127 //               type.
00128 //
00129 //               If magic_number is nonempty, it is assumed to
00130 //               represent the first few bytes that have already been
00131 //               read from the file.  Some file types may have
00132 //               difficulty if this is more than two bytes.
00133 //
00134 //               If type is non-NULL, it is a suggestion for the file
00135 //               type to use.
00136 //
00137 //               The PNMReader should be deleted when it is no longer
00138 //               needed.
00139 ////////////////////////////////////////////////////////////////////
00140 PNMReader *PNMImageHeader::
00141 make_reader(istream *file, bool owns_file, const Filename &filename,
00142             string magic_number, PNMFileType *type) const {
00143   if (type == (PNMFileType *)NULL) {
00144     if (!read_magic_number(file, magic_number, 2)) {
00145       // No magic number.  No image.
00146       if (pnmimage_cat.is_debug()) {
00147         pnmimage_cat.debug()
00148           << "Image file appears to be empty.\n";
00149       }
00150       if (owns_file) {
00151         delete file;
00152       }
00153       return NULL;
00154     }
00155 
00156     type = PNMFileTypeRegistry::get_ptr()->
00157       get_type_from_magic_number(magic_number);
00158 
00159     if (pnmimage_cat.is_debug()) {
00160       if (type != (PNMFileType *)NULL) {
00161         pnmimage_cat.debug()
00162           << "By magic number, image file appears to be type "
00163           << type->get_name() << ".\n";
00164       } else {
00165         pnmimage_cat.debug()
00166           << "Unable to determine image file type from magic number.\n";
00167       }
00168     }
00169   }
00170 
00171   if (type == (PNMFileType *)NULL && !filename.empty()) {
00172     // We still don't know the type; attempt to guess it from the
00173     // filename extension.
00174     type = PNMFileTypeRegistry::get_ptr()->get_type_from_extension(filename);
00175 
00176     if (pnmimage_cat.is_debug()) {
00177       if (type != (PNMFileType *)NULL) {
00178         pnmimage_cat.debug()
00179           << "From its extension, image file is probably type "
00180           << type->get_name() << ".\n";
00181       } else {
00182         pnmimage_cat.debug()
00183           << "Unable to guess image file type from its extension.\n";
00184       }
00185     }
00186   }
00187 
00188   if (type == (PNMFileType *)NULL) {
00189     // No?  How about the default type associated with this image header.
00190     type = _type;
00191 
00192     if (pnmimage_cat.is_debug() && type != (PNMFileType *)NULL) {
00193       pnmimage_cat.debug()
00194         << "Assuming image file type is " << type->get_name() << ".\n";
00195     }
00196   }
00197 
00198   if (type == (PNMFileType *)NULL) {
00199     // We can't figure out what type the file is; give up.
00200     if (pnmimage_cat.is_error()) {
00201       pnmimage_cat.error()
00202         << "Cannot determine type of image file " << filename << ".\n"
00203         << "Currently supported image types:\n";
00204       PNMFileTypeRegistry::get_ptr()->
00205         write_types(pnmimage_cat.error(false), 2);
00206     }
00207     if (owns_file) {
00208       delete file;
00209     }
00210     return NULL;
00211   }
00212 
00213   PNMReader *reader = type->make_reader(file, owns_file, magic_number);
00214   if (reader == NULL && owns_file) {
00215     delete file;
00216   }
00217 
00218   if (!reader->is_valid()) {
00219     delete reader;
00220     reader = NULL;
00221   }
00222 
00223   return reader;
00224 }
00225 
00226 ////////////////////////////////////////////////////////////////////
00227 //     Function: PNMImageHeader::make_writer
00228 //       Access: Public
00229 //  Description: Returns a newly-allocated PNMWriter of the suitable
00230 //               type for writing an image to the indicated filename,
00231 //               or NULL if the filename cannot be written for some
00232 //               reason.  The filename "-" always stands for standard
00233 //               output.  If type is specified, it is a suggestion for
00234 //               the file type to use.
00235 //
00236 //               The PNMWriter should be deleted when it is no longer
00237 //               needed.
00238 ////////////////////////////////////////////////////////////////////
00239 PNMWriter *PNMImageHeader::
00240 make_writer(const Filename &filename, PNMFileType *type) const {
00241   if (pnmimage_cat.is_debug()) {
00242     pnmimage_cat.debug()
00243       << "Writing image to " << filename << "\n";
00244   }
00245   bool owns_file = false;
00246   ostream *file = (ostream *)NULL;
00247 
00248   if (filename == "-") {
00249     owns_file = false;
00250     file = &cout;
00251 
00252     if (pnmimage_cat.is_debug()) {
00253       pnmimage_cat.debug()
00254         << "(writing to standard output)\n";
00255     }
00256 
00257   } else {
00258     ofstream *new_ostream = new ofstream;
00259     Filename actual_name = Filename::binary_filename(filename);
00260     if (!actual_name.open_write(*new_ostream)) {
00261       delete new_ostream;
00262       
00263     } else {
00264       owns_file = true;
00265       file = new_ostream;
00266     }
00267   }
00268 
00269   if (file == (ostream *)NULL) {
00270     if (pnmimage_cat.is_debug()) {
00271       pnmimage_cat.debug()
00272         << "Unable to write to file.\n";
00273     }
00274     return NULL;
00275   }
00276 
00277   return make_writer(file, owns_file, filename, type);
00278 }
00279 
00280 ////////////////////////////////////////////////////////////////////
00281 //     Function: PNMImageHeader::make_writer
00282 //       Access: Public
00283 //  Description: Returns a newly-allocated PNMWriter of the suitable
00284 //               type for writing to the already-opened image file, or
00285 //               NULL if the file cannot be written for some reason.
00286 //
00287 //               owns_file should be set true if the PNMWriter is to
00288 //               be considered the owner of the stream pointer (in
00289 //               which case the stream will be deleted on completion,
00290 //               whether successful or not), or false if it should not
00291 //               delete it.
00292 //
00293 //               The filename parameter is optional here, since the
00294 //               file has already been opened; it is only used to
00295 //               examine the extension and attempt to guess the
00296 //               intended file type.
00297 //
00298 //               If type is non-NULL, it is a suggestion for the file
00299 //               type to use.
00300 //
00301 //               The PNMWriter should be deleted when it is no longer
00302 //               needed.
00303 ////////////////////////////////////////////////////////////////////
00304 PNMWriter *PNMImageHeader::
00305 make_writer(ostream *file, bool owns_file, const Filename &filename,
00306             PNMFileType *type) const {
00307   if (type == (PNMFileType *)NULL && !filename.empty()) {
00308     // We don't know the type; attempt to guess it from the filename
00309     // extension.
00310     type = PNMFileTypeRegistry::get_ptr()->get_type_from_extension(filename);
00311 
00312     if (pnmimage_cat.is_debug()) {
00313       if (type != (PNMFileType *)NULL) {
00314         pnmimage_cat.debug()
00315           << "From its extension, image file is intended to be type "
00316           << type->get_name() << ".\n";
00317       } else {
00318         pnmimage_cat.debug()
00319           << "Unable to guess image file type from its extension.\n";
00320       }
00321     }
00322   }
00323 
00324   if (type == (PNMFileType *)NULL) {
00325     // No?  How about the default type associated with this image header.
00326     type = _type;
00327 
00328     if (pnmimage_cat.is_debug() && type != (PNMFileType *)NULL) {
00329       pnmimage_cat.debug()
00330         << "Assuming image file type is " << type->get_name() << ".\n";
00331     }
00332   }
00333 
00334   if (type == (PNMFileType *)NULL) {
00335     // We can't figure out what type the file is; give up.
00336     if (pnmimage_cat.is_debug()) {
00337       pnmimage_cat.debug()
00338         << "Cannot determine type of image file " << filename << ".\n";
00339     }
00340     if (owns_file) {
00341       delete file;
00342     }
00343     return NULL;
00344   }
00345 
00346   PNMWriter *writer = type->make_writer(file, owns_file);
00347   if (writer == NULL && owns_file) {
00348     delete file;
00349   }
00350 
00351   return writer;
00352 }
00353 
00354 ////////////////////////////////////////////////////////////////////
00355 //     Function: PNMImageHeader::read_magic_number
00356 //       Access: Public, Static
00357 //  Description: Ensures that the first n bytes of the file are read
00358 //               into magic_number.  If magic_number is initially
00359 //               nonempty, assumes these represent the first few bytes
00360 //               already extracted.  Returns true if successful, false
00361 //               if an end of file or error occurred before num_bytes
00362 //               could be read.
00363 ////////////////////////////////////////////////////////////////////
00364 bool PNMImageHeader::
00365 read_magic_number(istream *file, string &magic_number, int num_bytes) {
00366   while ((int)magic_number.size() < num_bytes) {
00367     int ch = file->get();
00368     if (file->eof() || file->fail()) {
00369       return false;
00370     }
00371     magic_number += (char)ch;
00372   }
00373 
00374   return true;
00375 }
00376 
00377 ////////////////////////////////////////////////////////////////////
00378 //     Function: PNMImageHeader::output
00379 //       Access: Public
00380 //  Description:
00381 ////////////////////////////////////////////////////////////////////
00382 void PNMImageHeader::
00383 output(ostream &out) const {
00384   out << "image: " << _x_size << " by " << _y_size << " pixels, "
00385       << _num_channels << " channels, " << _maxval << " maxval.";
00386 }

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