|
@@ -16,9 +16,6 @@
|
|
|
//
|
|
//
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Includes
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
#include "pandabase.h"
|
|
#include "pandabase.h"
|
|
|
#include "texture.h"
|
|
#include "texture.h"
|
|
|
#include "config_gobj.h"
|
|
#include "config_gobj.h"
|
|
@@ -33,12 +30,8 @@
|
|
|
#include <stddef.h>
|
|
#include <stddef.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Static variables
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
TypeHandle Texture::_type_handle;
|
|
TypeHandle Texture::_type_handle;
|
|
|
|
|
|
|
|
-
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: up_to_power_2
|
|
// Function: up_to_power_2
|
|
|
// Description: Returns the smallest power of 2 greater than or equal
|
|
// Description: Returns the smallest power of 2 greater than or equal
|
|
@@ -110,6 +103,28 @@ consider_rescale(PNMImage &pnmimage, const string &name) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: consider_downgrade
|
|
|
|
|
+// Description: Reduces the number of channels in the texture, if
|
|
|
|
|
+// necessary, according to num_components.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+static void
|
|
|
|
|
+consider_downgrade(PNMImage &pnmimage, int num_components,
|
|
|
|
|
+ const string &name) {
|
|
|
|
|
+ if (num_components != 0 && num_components < pnmimage.get_num_channels()) {
|
|
|
|
|
+ // One special case: we can't reduce from 3 to 2 components, since
|
|
|
|
|
+ // that would require adding an alpha channel.
|
|
|
|
|
+ if (pnmimage.get_num_channels() == 3 && num_components == 2) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ gobj_cat.info()
|
|
|
|
|
+ << "Downgrading " << name << " from " << pnmimage.get_num_channels()
|
|
|
|
|
+ << " components to " << num_components << ".\n";
|
|
|
|
|
+ pnmimage.set_num_channels(num_components);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: Constructor
|
|
// Function: Constructor
|
|
|
// Access: Published
|
|
// Access: Published
|
|
@@ -163,10 +178,13 @@ Texture::
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: read
|
|
// Function: read
|
|
|
// Access: Published
|
|
// Access: Published
|
|
|
-// Description: Reads the texture from the indicated filename.
|
|
|
|
|
|
|
+// Description: Reads the texture from the indicated filename. If
|
|
|
|
|
+// num_components is not 0, it specifies the number of
|
|
|
|
|
+// components to downgrade the image to if it is greater
|
|
|
|
|
+// than this number.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
bool Texture::
|
|
bool Texture::
|
|
|
-read(const Filename &fullpath) {
|
|
|
|
|
|
|
+read(const Filename &fullpath, int num_components) {
|
|
|
PNMImage image;
|
|
PNMImage image;
|
|
|
|
|
|
|
|
if (!image.read(fullpath)) {
|
|
if (!image.read(fullpath)) {
|
|
@@ -188,7 +206,7 @@ read(const Filename &fullpath) {
|
|
|
|
|
|
|
|
// Check to see if we need to scale it.
|
|
// Check to see if we need to scale it.
|
|
|
consider_rescale(image, get_name());
|
|
consider_rescale(image, get_name());
|
|
|
-
|
|
|
|
|
|
|
+ consider_downgrade(image, num_components, get_name());
|
|
|
return load(image);
|
|
return load(image);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -199,7 +217,8 @@ read(const Filename &fullpath) {
|
|
|
// to get a 4-component image
|
|
// to get a 4-component image
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
bool Texture::
|
|
bool Texture::
|
|
|
-read(const Filename &fullpath, const Filename &alpha_fullpath) {
|
|
|
|
|
|
|
+read(const Filename &fullpath, const Filename &alpha_fullpath,
|
|
|
|
|
+ int num_components) {
|
|
|
PNMImage image;
|
|
PNMImage image;
|
|
|
if (!image.read(fullpath)) {
|
|
if (!image.read(fullpath)) {
|
|
|
gobj_cat.error()
|
|
gobj_cat.error()
|
|
@@ -244,22 +263,16 @@ read(const Filename &fullpath, const Filename &alpha_fullpath) {
|
|
|
alpha_image = scaled;
|
|
alpha_image = scaled;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Make the original image a 4-component image
|
|
|
|
|
|
|
+ // Make the original image a 4-component image by taking the
|
|
|
|
|
+ // grayscale value from the second image.
|
|
|
image.add_alpha();
|
|
image.add_alpha();
|
|
|
- if (alpha_image.has_alpha()) {
|
|
|
|
|
- for (int x = 0; x < image.get_x_size(); x++) {
|
|
|
|
|
- for (int y = 0; y < image.get_y_size(); y++) {
|
|
|
|
|
- image.set_alpha(x, y, alpha_image.get_alpha(x, y));
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- for (int x = 0; x < image.get_x_size(); x++) {
|
|
|
|
|
- for (int y = 0; y < image.get_y_size(); y++) {
|
|
|
|
|
- image.set_alpha(x, y, alpha_image.get_gray(x, y));
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ for (int x = 0; x < image.get_x_size(); x++) {
|
|
|
|
|
+ for (int y = 0; y < image.get_y_size(); y++) {
|
|
|
|
|
+ image.set_alpha(x, y, alpha_image.get_gray(x, y));
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ consider_downgrade(image, num_components, get_name());
|
|
|
return load(image);
|
|
return load(image);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -687,10 +700,17 @@ make_Texture(const FactoryParams ¶ms) {
|
|
|
string name;
|
|
string name;
|
|
|
Filename filename, alpha_filename;
|
|
Filename filename, alpha_filename;
|
|
|
|
|
|
|
|
|
|
+ // Get the properties written by ImageBuffer::write_datagram().
|
|
|
name = scan.get_string();
|
|
name = scan.get_string();
|
|
|
filename = scan.get_string();
|
|
filename = scan.get_string();
|
|
|
alpha_filename = scan.get_string();
|
|
alpha_filename = scan.get_string();
|
|
|
|
|
|
|
|
|
|
+ // Get the expected number of components.
|
|
|
|
|
+ int num_components = 0;
|
|
|
|
|
+ if (manager->get_file_minor_ver() >= 2) {
|
|
|
|
|
+ num_components = scan.get_uint8();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
PT(Texture) me;
|
|
PT(Texture) me;
|
|
|
|
|
|
|
|
if (filename.empty()) {
|
|
if (filename.empty()) {
|
|
@@ -702,9 +722,9 @@ make_Texture(const FactoryParams ¶ms) {
|
|
|
} else {
|
|
} else {
|
|
|
// This texture does have a filename, so try to load it from disk.
|
|
// This texture does have a filename, so try to load it from disk.
|
|
|
if (alpha_filename.empty()) {
|
|
if (alpha_filename.empty()) {
|
|
|
- me = TexturePool::load_texture(filename);
|
|
|
|
|
|
|
+ me = TexturePool::load_texture(filename, num_components);
|
|
|
} else {
|
|
} else {
|
|
|
- me = TexturePool::load_texture(filename, alpha_filename);
|
|
|
|
|
|
|
+ me = TexturePool::load_texture(filename, alpha_filename, num_components);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -774,19 +794,29 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void Texture::
|
|
void Texture::
|
|
|
write_datagram(BamWriter *manager, Datagram &me) {
|
|
write_datagram(BamWriter *manager, Datagram &me) {
|
|
|
|
|
+ // We also need to write out the pixel buffer's format, even though
|
|
|
|
|
+ // that's not stored as part of the texture structure.
|
|
|
|
|
+ bool has_pbuffer = (_pbuffer != (PixelBuffer *)NULL);
|
|
|
|
|
+
|
|
|
|
|
+ // These properties are read in again by make_Texture(), above.
|
|
|
ImageBuffer::write_datagram(manager, me);
|
|
ImageBuffer::write_datagram(manager, me);
|
|
|
|
|
+ if (has_pbuffer) {
|
|
|
|
|
+ me.add_uint8(_pbuffer->get_num_components());
|
|
|
|
|
+ } else {
|
|
|
|
|
+ me.add_uint8(0);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // These properties are read in again by fillin(), above.
|
|
|
me.add_uint8(_wrapu);
|
|
me.add_uint8(_wrapu);
|
|
|
me.add_uint8(_wrapv);
|
|
me.add_uint8(_wrapv);
|
|
|
me.add_uint8(_minfilter);
|
|
me.add_uint8(_minfilter);
|
|
|
me.add_uint8(_magfilter);
|
|
me.add_uint8(_magfilter);
|
|
|
me.add_int16(_anisotropic_degree);
|
|
me.add_int16(_anisotropic_degree);
|
|
|
|
|
|
|
|
- // We also need to write out the pixel buffer's format, even though
|
|
|
|
|
- // that's not stored as part of the texture structure.
|
|
|
|
|
- bool has_pbuffer = (_pbuffer != (PixelBuffer *)NULL);
|
|
|
|
|
me.add_bool(has_pbuffer);
|
|
me.add_bool(has_pbuffer);
|
|
|
if (has_pbuffer) {
|
|
if (has_pbuffer) {
|
|
|
me.add_uint8(_pbuffer->get_format());
|
|
me.add_uint8(_pbuffer->get_format());
|
|
|
|
|
+ // I know this has already been written, above.
|
|
|
me.add_uint8(_pbuffer->get_num_components());
|
|
me.add_uint8(_pbuffer->get_num_components());
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|