Procházet zdrojové kódy

*** empty log message ***

David Rose před 25 roky
rodič
revize
827d1ac12d

+ 157 - 1
pandatool/src/egg-palettize/attribFile.cxx

@@ -13,6 +13,10 @@
 #include "palette.h"
 #include "sourceEgg.h"
 
+#include <pnmImage.h>
+#include <pnmFileType.h>
+#include <pnmFileTypeRegistry.h>
+
 #include <ctype.h>
 #include <errno.h>
 #include <stdio.h>
@@ -53,6 +57,8 @@ AttribFile(const Filename &filename) {
   _default_margin = 2;
   _force_power_2 = false;
   _aggressively_clean_mapdir = false;
+  _color_type = (PNMFileType *)NULL;
+  _alpha_type = (PNMFileType *)NULL;
 }
 
 string AttribFile::
@@ -107,6 +113,12 @@ open_and_lock(bool lock) {
 
   if (lock) {
     if (fcntl(_txa_fd, F_SETLK, &fl) < 0) {
+      if (errno != EACCES) {
+	perror(_txa_filename.c_str());
+	nout << "Unable to lock file; try running with -nolock.\n";
+	return false;
+      }
+
       nout << "Waiting for lock on " << _txa_filename << "\n";
       while (fcntl(_txa_fd, F_SETLKW, &fl) < 0) {
 	if (errno != EINTR) {
@@ -252,6 +264,10 @@ update_params(EggPalettize *prog) {
   if (prog->_got_aggressively_clean_mapdir) {
     _aggressively_clean_mapdir = prog->_aggressively_clean_mapdir;
   }
+  if (prog->_got_image_type) {
+    _color_type = prog->_color_type;
+    _alpha_type = prog->_alpha_type;
+  }
 
   if (!_rel_dirname.empty()) {
     _rel_dirname.make_canonical();
@@ -655,6 +671,13 @@ transfer_unplaced_images(bool force_redo_all) {
 	  nout << "Deleting " << new_filename << "\n";
 	  new_filename.unlink();
 	}
+	if (packing->has_alpha_filename()) {
+	  Filename alpha_filename = packing->get_alpha_filename();
+	  if (alpha_filename.exists()) {
+	    nout << "Deleting " << alpha_filename << "\n";
+	    alpha_filename.unlink();
+	  }
+	}
       }
     }
   }
@@ -780,6 +803,110 @@ collect_statistics(int &num_textures, int &num_placed, int &num_palettes,
 }  
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AttribFile::make_color_filename
+//       Access: Public
+//  Description: Adjusts an image filename to a suitable filename for
+//               saving the color channel.
+////////////////////////////////////////////////////////////////////
+Filename AttribFile::
+make_color_filename(const Filename &filename) const {
+  Filename color_filename = filename;
+  if (_color_type != (PNMFileType *)NULL) {
+    color_filename.set_extension(_color_type->get_suggested_extension());
+  }
+  return color_filename;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AttribFile::make_alpha_filename
+//       Access: Public
+//  Description: Adjusts an image filename to a suitable filename for
+//               saving the alpha channel, if one is to be saved.
+////////////////////////////////////////////////////////////////////
+Filename AttribFile::
+make_alpha_filename(const Filename &filename) const {
+  Filename alpha_filename;
+  if (_alpha_type != (PNMFileType *)NULL) {
+    alpha_filename = filename;
+    alpha_filename.set_basename
+      (filename.get_basename_wo_extension() + "_alpha." + 
+       _alpha_type->get_suggested_extension());
+  }
+  return alpha_filename;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AttribFile::write_image_file
+//       Access: Public
+//  Description: Writes out the indicated image, either as a single
+//               file with or without alpha, or as two separate files
+//               if necessary.
+////////////////////////////////////////////////////////////////////
+bool AttribFile::
+write_image_file(PNMImage &image, const Filename &filename,
+		 const Filename &alpha_filename) const {
+  if (!image.has_alpha() || _alpha_type == (PNMFileType *)NULL) {
+    if (!alpha_filename.empty() && alpha_filename.exists()) {
+      alpha_filename.unlink();
+    }
+    return image.write(filename, _color_type);
+  }
+
+  // Write out a separate color image and an alpha channel image.
+  PNMImage alpha_image(image.get_x_size(), image.get_y_size(), 1,
+		       image.get_maxval());
+  for (int y = 0; y < image.get_y_size(); y++) {
+    for (int x = 0; x < image.get_x_size(); x++) {
+      alpha_image.set_gray_val(x, y, image.get_alpha_val(x, y));
+    }
+  }
+
+  image.remove_alpha();
+  return
+    image.write(filename, _color_type) && 
+    alpha_image.write(alpha_filename, _alpha_type);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AttribFile::read_image_file
+//       Access: Public
+//  Description: Reads in the indicated image, either as a single
+//               file with or without alpha, or as two separate files
+//               if necessary.
+////////////////////////////////////////////////////////////////////
+bool AttribFile::
+read_image_file(PNMImage &image, const Filename &filename,
+		const Filename &alpha_filename) const {
+  image.set_type(_color_type);
+  if (!image.read(filename)) {
+    return false;
+  }
+
+  if (!alpha_filename.empty() && alpha_filename.exists()) {
+    // Read in a separate color image and an alpha channel image.
+    PNMImage alpha_image;
+    alpha_image.set_type(_alpha_type);
+    if (!alpha_image.read(alpha_filename)) {
+      return false;
+    }
+    if (image.get_x_size() != alpha_image.get_x_size() ||
+	image.get_y_size() != alpha_image.get_y_size()) {
+      return false;
+    }
+
+    image.add_alpha();
+    for (int y = 0; y < image.get_y_size(); y++) {
+      for (int x = 0; x < image.get_x_size(); x++) {
+	image.set_alpha(x, y, alpha_image.get_gray(x, y));
+      }
+    }
+  }
+
+  return true;
+}
+
+
 bool AttribFile::
 read_txa(istream &infile) {
   string line;
@@ -901,7 +1028,16 @@ write_pi(ostream &out) const {
       << "  pal_ysize " << _pal_ysize << "\n"
       << "  default_margin " << _default_margin << "\n"
       << "  force_power_2 " << _force_power_2 << "\n"
-      << "  aggressively_clean_mapdir " << _aggressively_clean_mapdir << "\n";
+      << "  aggressively_clean_mapdir " << _aggressively_clean_mapdir << "\n"
+      << "  color_type";
+  if (_color_type != (PNMFileType *)NULL) {
+    out << " " << _color_type->get_suggested_extension();
+  }
+  out << "\n  alpha_type";
+  if (_alpha_type != (PNMFileType *)NULL) {
+    out << " " << _alpha_type->get_suggested_extension();
+  }
+  out << "\n";
 
   if (_optimal) {
     out << "\npacking is optimal\n";
@@ -1012,6 +1148,26 @@ parse_params(const vector_string &words, istream &infile,
       _force_power_2 = (atoi(value.c_str()) != 0);
     } else if (param == "aggressively_clean_mapdir") {
       _aggressively_clean_mapdir = (atoi(value.c_str()) != 0);
+    } else if (param == "color_type") {
+      if (value.empty()) {
+	_color_type = (PNMFileType *)NULL;
+      } else {
+	PNMFileTypeRegistry *registry = PNMFileTypeRegistry::get_ptr();
+	_color_type = registry->get_type_from_extension(value);
+	if (_color_type == (PNMFileType *)NULL) {
+	  nout << "Warning: unknown image file type: " << value << "\n";
+	}
+      }
+    } else if (param == "alpha_type") {
+      if (value.empty()) {
+	_alpha_type = (PNMFileType *)NULL;
+      } else {
+	PNMFileTypeRegistry *registry = PNMFileTypeRegistry::get_ptr();
+	_alpha_type = registry->get_type_from_extension(value);
+	if (_alpha_type == (PNMFileType *)NULL) {
+	  nout << "Warning: unknown image file type: " << value << "\n";
+	}
+      }
     } else {
       nout << "Unexpected keyword: " << param << "\n";
       return false;

+ 13 - 0
pandatool/src/egg-palettize/attribFile.h

@@ -21,6 +21,8 @@ class PaletteGroup;
 class Palette;
 class SourceEgg;
 class EggPalettize;
+class PNMImage;
+class PNMFileType;
 
 ////////////////////////////////////////////////////////////////////
 // 	 Class : AttribFile
@@ -77,6 +79,14 @@ public:
 			  int &orig_size, int &resized_size, 
 			  int &palette_size, int &unplaced_size) const;
 
+  Filename make_color_filename(const Filename &filename) const;
+  Filename make_alpha_filename(const Filename &filename) const;
+
+  bool write_image_file(PNMImage &image, const Filename &filename,
+			const Filename &alpha_filename) const;
+  bool read_image_file(PNMImage &image, const Filename &filename,
+		       const Filename &alpha_filename) const;
+
 private:
   typedef vector<UserAttribLine *> UserLines;
   UserLines _user_lines;
@@ -141,6 +151,9 @@ public:
   bool _force_power_2;
   bool _aggressively_clean_mapdir;
 
+  PNMFileType *_color_type;
+  PNMFileType *_alpha_type;
+
   int _txa_fd;
   fstream _txa_fstrm;
 

+ 72 - 0
pandatool/src/egg-palettize/eggPalettize.cxx

@@ -11,6 +11,8 @@
 #include "textureOmitReason.h"
 
 #include <pnmImage.h>
+#include <pnmFileTypeRegistry.h>
+#include <pnmFileType.h>
 #include <stdio.h>
 
 ////////////////////////////////////////////////////////////////////
@@ -122,6 +124,15 @@ EggPalettize() : EggMultiFilter(true) {
      "Aggressively keep the map directory clean by deleting unused "
      "textures from previous passes.",
      &EggPalettize::dispatch_none, &_got_aggressively_clean_mapdir);
+  add_option
+    ("type", "imagetype[,alphatype]", 0, 
+     "Specify the type of image file to output.  All image files, whether "
+     "palettes or unplaced textures, will be converted to files of this "
+     "type.  If the optional alpha type is specified, then an alpha channel, "
+     "if present, will be written as a separate file of the indicated "
+     "type--useful if the primary image type does not support alpha.  "
+     "Use '-type list' to show the available image types.",
+     &EggPalettize::dispatch_string, &_got_image_type, &_image_type);
   add_option
     ("r", "", 0, 
      "Respect any repeat/clamp flags given in the egg files.  The "
@@ -168,6 +179,8 @@ EggPalettize() : EggMultiFilter(true) {
   _fuzz_factor = 0.01;
   _aggressively_clean_mapdir = false;
   _force_power_2 = false;
+  _color_type = (PNMFileType *)NULL;
+  _alpha_type = (PNMFileType *)NULL;
 }
 
 
@@ -186,6 +199,65 @@ handle_args(ProgramBase::Args &args) {
     exit(1);
   }
 
+  if (_got_image_type) {
+    PNMFileTypeRegistry *registry = PNMFileTypeRegistry::get_ptr();
+
+    if (_image_type == "list") {
+      nout << "Known image types are:\n";
+      registry->write_types(nout, 2);
+      nout << "\n";
+      exit(1);
+    }
+
+    string color_name = _image_type;
+    string alpha_name;
+    size_t comma = _image_type.find(',');
+    if (comma != string::npos) {
+      // If we have a comma in the image_type, it's two types: a color
+      // type and an alpha type.
+      color_name = _image_type.substr(0, comma);
+      alpha_name = _image_type.substr(comma + 1);
+    }
+
+    bool okflag = true;
+
+    if (!color_name.empty()) {
+      _color_type = registry->get_type_from_extension(color_name);
+      if (_color_type == (PNMFileType *)NULL) {
+	nout << "Image file type '" << color_name << "' is unknown.\n";
+	okflag = false;
+      }
+    }
+
+    if (!alpha_name.empty()) {
+      _alpha_type = registry->get_type_from_extension(alpha_name);
+      if (_alpha_type == (PNMFileType *)NULL) {
+	nout << "Image file type '" << alpha_name << "' is unknown.\n";
+	okflag = false;
+      }
+    }
+
+    if (!okflag) {
+      nout << "\nKnown image types are:\n";
+      registry->write_types(nout, 2);
+      nout << "\n";
+      exit(1);
+    }
+
+    /*
+    if (_color_type != (PNMFileType *)NULL && 
+	_alpha_type != (PNMFileType *)NULL) {
+      nout << "Writing color components to " << _color_type->get_name()
+	   << " and alpha components to " << _alpha_type->get_name()
+	   << " files.\n";
+
+    } else if (_color_type != (PNMFileType *)NULL) {
+      nout << "Converting images to " << _color_type->get_name()
+	   << " files.\n";
+    }
+    */
+  }
+
   Args egg_names;
   Args txa_names;
 

+ 5 - 0
pandatool/src/egg-palettize/eggPalettize.h

@@ -14,6 +14,7 @@
 #include <vector>
 
 class PTexture;
+class PNMFileType;
 
 ////////////////////////////////////////////////////////////////////
 // 	 Class : EggPalettize
@@ -54,6 +55,10 @@ public:
   bool _got_force_power_2;
   bool _aggressively_clean_mapdir;
   bool _got_aggressively_clean_mapdir;
+  string _image_type;
+  bool _got_image_type;
+  PNMFileType *_color_type;
+  PNMFileType *_alpha_type;
 
   // The following values relate specifically to egg files.  They're
   // not saved for future sessions.

+ 0 - 14
pandatool/src/egg-palettize/imageFile.cxx

@@ -1,14 +0,0 @@
-// Filename: imageFile.cxx
-// Created by:  drose (07Sep99)
-// 
-////////////////////////////////////////////////////////////////////
-
-#include "imageFile.h"
-
-ImageFile::
-ImageFile() {
-}
-
-ImageFile::
-~ImageFile() {
-}

+ 0 - 28
pandatool/src/egg-palettize/imageFile.h

@@ -1,28 +0,0 @@
-// Filename: imageFile.h
-// Created by:  drose (07Sep99)
-// 
-////////////////////////////////////////////////////////////////////
-
-#ifndef IMAGEFILE_H
-#define IMAGEFILE_H
-
-#include <pandatoolbase.h>
-
-#include <filename.h>
-
-////////////////////////////////////////////////////////////////////
-// 	 Class : ImageFile
-// Description : This is the base class for both Palette and PTexture.
-////////////////////////////////////////////////////////////////////
-class ImageFile {
-public:
-  ImageFile();
-  virtual ~ImageFile();
-
-  virtual Filename get_filename() const=0;
-  virtual Filename get_basename() const=0;
-
-};
-
-#endif
-

+ 2 - 1
pandatool/src/egg-palettize/pTexture.cxx

@@ -382,7 +382,7 @@ read_image() {
   }
 
   PNMImage *image = new PNMImage;
-  if (image->read(_filename)) {
+  if (_attrib_file->read_image_file(*image, _filename, Filename())) {
     return image;
   }
 
@@ -431,5 +431,6 @@ read_image_header(const Filename &filename, int &xsize, int &ysize,
   xsize = header.get_x_size();
   ysize = header.get_y_size();
   zsize = header.get_num_channels();
+
   return true;
 }

+ 39 - 4
pandatool/src/egg-palettize/palette.cxx

@@ -12,6 +12,7 @@
 
 #include <notify.h>
 #include <pnmImage.h>
+#include <pnmFileType.h>
 
 bool Palette::TexturePlacement::
 intersects(int hleft, int htop, int xsize, int ysize) const {
@@ -149,6 +150,7 @@ Palette(const Filename &filename, PaletteGroup *group,
   _index = -1;
   _palette_changed = false;
   _new_palette = false;
+  _uses_alpha = (_components == 2 || _components == 4);
 }
 
 Palette::
@@ -163,6 +165,7 @@ Palette(PaletteGroup *group, int index,
 {
   _palette_changed = false;
   _new_palette = true;
+  _uses_alpha = (_components == 2 || _components == 4);
 }
 
 Palette::
@@ -179,6 +182,29 @@ get_filename() const {
   return _filename;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Palette::has_alpha_filename
+//       Access: Public
+//  Description: Returns true if this texture requires a separate
+//               alpha image file.
+////////////////////////////////////////////////////////////////////
+bool Palette::
+has_alpha_filename() const {
+  return _uses_alpha && (_attrib_file->_alpha_type != (PNMFileType *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Palette::get_alpha_filename
+//       Access: Public
+//  Description: Returns the filename for the alpha channel to which
+//               this texture will be copied, assuming it is not
+//               placed on a palette.
+////////////////////////////////////////////////////////////////////
+Filename Palette::
+get_alpha_filename() const {
+  return _attrib_file->make_alpha_filename(_filename);
+}
+
 Filename Palette::
 get_basename() const {
   return _basename;
@@ -331,15 +357,18 @@ finalize_palette() {
     char index_str[128];
     sprintf(index_str, "%03d", _index);
     _basename = _group->get_name() + "-palette." + index_str + ".rgb";
+    _basename = _attrib_file->make_color_filename(_basename);
 
     Filename dirname = _group->get_full_dirname(_attrib_file);
     _filename = _basename;
     _filename.set_dirname(dirname.get_fullpath());
   } else {
+    _filename = _attrib_file->make_color_filename(_filename);
     _basename = _filename.get_basename();
   }
 
-  _components = check_uses_alpha() ? 4 : 3;
+  _uses_alpha = check_uses_alpha();
+  _components = _uses_alpha ? 4 : 3;
 
   if (_texplace.size() == 1) {
     // If we packed exactly one texture, never mind.
@@ -388,7 +417,7 @@ generate_image() {
   }
 
   _filename.make_dir();
-  if (!palette.write(_filename)) {
+  if (!_attrib_file->write_image_file(palette, _filename, get_alpha_filename())) {
     nout << "Error in writing.\n";
     okflag = false;
   }
@@ -402,11 +431,17 @@ refresh_image() {
     nout << "Palette image " << _filename << " does not exist, rebuilding.\n";
     return generate_image();
   }
+  Filename alpha_filename = get_alpha_filename();
+  if (has_alpha_filename() && !alpha_filename.exists()) {
+    nout << "Palette alpha image " << alpha_filename
+	 << " does not exist, rebuilding.\n";
+    return generate_image();
+  }
 
   bool okflag = true;
 
   PNMImage palette;
-  if (!palette.read(_filename)) {
+  if (!_attrib_file->read_image_file(palette, _filename, alpha_filename)) {
     nout << "Unable to read old palette image " << _filename 
 	 << ", rebuilding.\n";
     return generate_image();
@@ -440,7 +475,7 @@ refresh_image() {
   }
 
   if (any_changed) {
-    if (!palette.write(_filename)) {
+    if (!_attrib_file->write_image_file(palette, _filename, alpha_filename)) {
       nout << "Error in writing.\n";
       okflag = false;
     }

+ 3 - 0
pandatool/src/egg-palettize/palette.h

@@ -35,6 +35,8 @@ public:
   ~Palette();
 
   Filename get_filename() const;
+  bool has_alpha_filename() const;
+  Filename get_alpha_filename() const;
   Filename get_basename() const;
 
   PaletteGroup *get_group() const;
@@ -88,6 +90,7 @@ private:
   PaletteGroup *_group;
   int _index;
   int _xsize, _ysize, _components;
+  bool _uses_alpha;
   bool _palette_changed;
   bool _new_palette;
   

+ 5 - 0
pandatool/src/egg-palettize/sourceEgg.cxx

@@ -290,6 +290,11 @@ update_trefs() {
 	// This texture wasn't palettized, so just rename the
 	// reference to the new one.
 	eggtex->set_filename(_attrib_file->write_egg_filename(packing->get_new_filename()));
+	if (packing->has_alpha_filename()) {
+	  eggtex->set_alpha_file(_attrib_file->write_egg_filename(packing->get_alpha_filename()));
+	} else {
+	  eggtex->clear_alpha_file();
+	}
 
       } else {
 	// This texture was palettized, so redirect the tref to point

+ 34 - 1
pandatool/src/egg-palettize/texturePacking.cxx

@@ -414,6 +414,15 @@ needs_refresh() {
     } else {
       // Compare to the resized file.
       target_filename = get_new_filename();
+
+      if (has_alpha_filename()) {
+	// If we have an alpha file, compare to the older of the two
+	// files.
+	Filename alpha_filename = get_alpha_filename();
+	if (target_filename.compare_timestamps(alpha_filename, true, true) > 0) {
+	  target_filename = alpha_filename;
+	}
+      }
     }
 
     if (!any_change) {
@@ -474,10 +483,34 @@ Filename TexturePacking::
 get_new_filename() const {
   Filename dirname = _group->get_full_dirname(_attrib_file);
   Filename new_filename(dirname, _texture->get_name());
+  new_filename = _attrib_file->make_color_filename(new_filename);
   new_filename.standardize();
   return new_filename;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePacking::has_alpha_filename
+//       Access: Public
+//  Description: Returns true if this texture requires a separate
+//               alpha image file.
+////////////////////////////////////////////////////////////////////
+bool TexturePacking::
+has_alpha_filename() const {
+  return _uses_alpha && (_attrib_file->_alpha_type != (PNMFileType *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePacking::get_alpha_filename
+//       Access: Public
+//  Description: Returns the filename for the alpha channel to which
+//               this texture will be copied, assuming it is not
+//               placed on a palette.
+////////////////////////////////////////////////////////////////////
+Filename TexturePacking::
+get_alpha_filename() const {
+  return _attrib_file->make_alpha_filename(get_new_filename());
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: TexturePacking::get_old_filename
 //       Access: Public
@@ -556,7 +589,7 @@ transfer() {
   }
   
   new_filename.make_dir();
-  if (!image->write(new_filename)) {
+  if (!_attrib_file->write_image_file(*image, new_filename, get_alpha_filename())) {
     nout << "Error in writing.\n";
     okflag = false;
   }

+ 2 - 0
pandatool/src/egg-palettize/texturePacking.h

@@ -61,6 +61,8 @@ public:
   void write_unplaced(ostream &out) const;
 
   Filename get_new_filename() const;
+  bool has_alpha_filename() const;
+  Filename get_alpha_filename() const;
   Filename get_old_filename() const;
   bool transfer();