mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
integrate PfmFile with PNMImage, Texture
This commit is contained in:
parent
5bd76de269
commit
7ba693137c
@ -28,6 +28,8 @@
|
|||||||
#include "string_utils.h"
|
#include "string_utils.h"
|
||||||
#include "preparedGraphicsObjects.h"
|
#include "preparedGraphicsObjects.h"
|
||||||
#include "pnmImage.h"
|
#include "pnmImage.h"
|
||||||
|
#include "pnmReader.h"
|
||||||
|
#include "pfmFile.h"
|
||||||
#include "virtualFileSystem.h"
|
#include "virtualFileSystem.h"
|
||||||
#include "datagramInputFile.h"
|
#include "datagramInputFile.h"
|
||||||
#include "datagramOutputFile.h"
|
#include "datagramOutputFile.h"
|
||||||
@ -2913,12 +2915,40 @@ do_read_one(CData *cdata, const Filename &fullpath, const Filename &alpha_fullpa
|
|||||||
}
|
}
|
||||||
|
|
||||||
PNMImage image;
|
PNMImage image;
|
||||||
if (header_only || textures_header_only) {
|
PfmFile pfm;
|
||||||
if (!image.read_header(fullpath)) {
|
PNMReader *image_reader = image.make_reader(fullpath, NULL, false);
|
||||||
|
if (image_reader == NULL) {
|
||||||
gobj_cat.error()
|
gobj_cat.error()
|
||||||
<< "Texture::read() - couldn't read: " << fullpath << endl;
|
<< "Texture::read() - couldn't read: " << fullpath << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
image.copy_header_from(*image_reader);
|
||||||
|
|
||||||
|
// If it's a single-channel floating-point image file, read it by
|
||||||
|
// default into a floating-point texture. (Multi-channel image
|
||||||
|
// files are ready as integers by default, since current graphics
|
||||||
|
// API's don't support multi-channel float textures.)
|
||||||
|
bool read_floating_point;
|
||||||
|
int texture_load_type = (options.get_texture_flags() & (LoaderOptions::TF_integer | LoaderOptions::TF_float));
|
||||||
|
switch (texture_load_type) {
|
||||||
|
case LoaderOptions::TF_integer:
|
||||||
|
read_floating_point = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LoaderOptions::TF_float:
|
||||||
|
read_floating_point = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Neither TF_integer nor TF_float was specified; determine which
|
||||||
|
// way the texture wants to be loaded.
|
||||||
|
read_floating_point = (image_reader->is_floating_point() && image_reader->get_num_channels() == 1);
|
||||||
|
if (!alpha_fullpath.empty()) {
|
||||||
|
read_floating_point = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header_only || textures_header_only) {
|
||||||
int x_size = image.get_x_size();
|
int x_size = image.get_x_size();
|
||||||
int y_size = image.get_y_size();
|
int y_size = image.get_y_size();
|
||||||
if (z == 0 && n == 0) {
|
if (z == 0 && n == 0) {
|
||||||
@ -2938,20 +2968,19 @@ do_read_one(CData *cdata, const Filename &fullpath, const Filename &alpha_fullpa
|
|||||||
y_size = image.get_read_y_size();
|
y_size = image.get_read_y_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (read_floating_point) {
|
||||||
|
pfm.clear(x_size, y_size, image.get_num_channels());
|
||||||
|
} else {
|
||||||
image = PNMImage(x_size, y_size, image.get_num_channels(),
|
image = PNMImage(x_size, y_size, image.get_num_channels(),
|
||||||
image.get_maxval(), image.get_type());
|
image.get_maxval(), image.get_type());
|
||||||
image.fill(0.2, 0.3, 1.0);
|
image.fill(0.2, 0.3, 1.0);
|
||||||
if (image.has_alpha()) {
|
if (image.has_alpha()) {
|
||||||
image.alpha_fill(1.0);
|
image.alpha_fill(1.0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
delete image_reader;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (!image.read_header(fullpath, NULL, false)) {
|
|
||||||
gobj_cat.error()
|
|
||||||
<< "Texture::read() - couldn't read: " << fullpath << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (z == 0 && n == 0) {
|
if (z == 0 && n == 0) {
|
||||||
cdata->_orig_file_x_size = image.get_x_size();
|
cdata->_orig_file_x_size = image.get_x_size();
|
||||||
cdata->_orig_file_y_size = image.get_y_size();
|
cdata->_orig_file_y_size = image.get_y_size();
|
||||||
@ -2970,7 +2999,14 @@ do_read_one(CData *cdata, const Filename &fullpath, const Filename &alpha_fullpa
|
|||||||
<< "\n";
|
<< "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!image.read(fullpath, NULL, false)) {
|
bool success;
|
||||||
|
if (read_floating_point) {
|
||||||
|
success = pfm.read(image_reader);
|
||||||
|
} else {
|
||||||
|
success = image.read(image_reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
gobj_cat.error()
|
gobj_cat.error()
|
||||||
<< "Texture::read() - couldn't read: " << fullpath << endl;
|
<< "Texture::read() - couldn't read: " << fullpath << endl;
|
||||||
return false;
|
return false;
|
||||||
@ -2980,16 +3016,19 @@ do_read_one(CData *cdata, const Filename &fullpath, const Filename &alpha_fullpa
|
|||||||
|
|
||||||
PNMImage alpha_image;
|
PNMImage alpha_image;
|
||||||
if (!alpha_fullpath.empty()) {
|
if (!alpha_fullpath.empty()) {
|
||||||
|
PNMReader *alpha_image_reader = alpha_image.make_reader(alpha_fullpath, NULL, false);
|
||||||
|
if (alpha_image_reader == NULL) {
|
||||||
|
gobj_cat.error()
|
||||||
|
<< "Texture::read() - couldn't read: " << alpha_fullpath << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
alpha_image.copy_header_from(*alpha_image_reader);
|
||||||
|
|
||||||
if (record != (BamCacheRecord *)NULL) {
|
if (record != (BamCacheRecord *)NULL) {
|
||||||
record->add_dependent_file(alpha_fullpath);
|
record->add_dependent_file(alpha_fullpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header_only || textures_header_only) {
|
if (header_only || textures_header_only) {
|
||||||
if (!alpha_image.read_header(alpha_fullpath)) {
|
|
||||||
gobj_cat.error()
|
|
||||||
<< "Texture::read() - couldn't read: " << alpha_fullpath << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int x_size = image.get_x_size();
|
int x_size = image.get_x_size();
|
||||||
int y_size = image.get_y_size();
|
int y_size = image.get_y_size();
|
||||||
alpha_image = PNMImage(x_size, y_size, alpha_image.get_num_channels(),
|
alpha_image = PNMImage(x_size, y_size, alpha_image.get_num_channels(),
|
||||||
@ -2998,14 +3037,9 @@ do_read_one(CData *cdata, const Filename &fullpath, const Filename &alpha_fullpa
|
|||||||
if (alpha_image.has_alpha()) {
|
if (alpha_image.has_alpha()) {
|
||||||
alpha_image.alpha_fill(1.0);
|
alpha_image.alpha_fill(1.0);
|
||||||
}
|
}
|
||||||
|
delete alpha_image_reader;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (!alpha_image.read_header(alpha_fullpath, NULL, true)) {
|
|
||||||
gobj_cat.error()
|
|
||||||
<< "Texture::read() - couldn't read (alpha): " << alpha_fullpath << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (image.get_x_size() != alpha_image.get_x_size() ||
|
if (image.get_x_size() != alpha_image.get_x_size() ||
|
||||||
image.get_y_size() != alpha_image.get_y_size()) {
|
image.get_y_size() != alpha_image.get_y_size()) {
|
||||||
gobj_cat.info()
|
gobj_cat.info()
|
||||||
@ -3016,7 +3050,7 @@ do_read_one(CData *cdata, const Filename &fullpath, const Filename &alpha_fullpa
|
|||||||
alpha_image.set_read_size(image.get_x_size(), image.get_y_size());
|
alpha_image.set_read_size(image.get_x_size(), image.get_y_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!alpha_image.read(alpha_fullpath, NULL, true)) {
|
if (!alpha_image.read(alpha_image_reader)) {
|
||||||
gobj_cat.error()
|
gobj_cat.error()
|
||||||
<< "Texture::read() - couldn't read (alpha): " << alpha_fullpath << endl;
|
<< "Texture::read() - couldn't read (alpha): " << alpha_fullpath << endl;
|
||||||
return false;
|
return false;
|
||||||
@ -3106,6 +3140,11 @@ do_read_one(CData *cdata, const Filename &fullpath, const Filename &alpha_fullpa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (read_floating_point) {
|
||||||
|
if (!do_load_one(cdata, pfm, fullpath.get_basename(), z, n, options)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// Now see if we want to pad the image within a larger power-of-2
|
// Now see if we want to pad the image within a larger power-of-2
|
||||||
// image.
|
// image.
|
||||||
int pad_x_size = 0;
|
int pad_x_size = 0;
|
||||||
@ -3128,6 +3167,7 @@ do_read_one(CData *cdata, const Filename &fullpath, const Filename &alpha_fullpa
|
|||||||
}
|
}
|
||||||
|
|
||||||
do_set_pad_size(cdata, pad_x_size, pad_y_size, 0);
|
do_set_pad_size(cdata, pad_x_size, pad_y_size, 0);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3205,6 +3245,74 @@ do_load_one(CData *cdata, const PNMImage &pnmimage, const string &name, int z, i
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Texture::do_load_one
|
||||||
|
// Access: Protected, Virtual
|
||||||
|
// Description: Internal method to load a single page or mipmap
|
||||||
|
// level.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool Texture::
|
||||||
|
do_load_one(CData *cdata, const PfmFile &pfm, const string &name, int z, int n,
|
||||||
|
const LoaderOptions &options) {
|
||||||
|
if (cdata->_ram_images.size() <= 1 && n == 0) {
|
||||||
|
// A special case for mipmap level 0. When we load mipmap level
|
||||||
|
// 0, unless we already have mipmap levels, it determines the
|
||||||
|
// image properties like size and number of components.
|
||||||
|
if (!do_reconsider_z_size(cdata, z, options)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
nassertr(z >= 0 && z < cdata->_z_size * cdata->_num_views, false);
|
||||||
|
|
||||||
|
if (z == 0) {
|
||||||
|
ComponentType component_type = T_float;
|
||||||
|
if (!do_reconsider_image_properties(cdata, pfm.get_x_size(), pfm.get_y_size(),
|
||||||
|
pfm.get_num_channels(), component_type,
|
||||||
|
z, options)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do_modify_ram_image(cdata);
|
||||||
|
cdata->_loaded_from_image = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_modify_ram_mipmap_image(cdata, n);
|
||||||
|
|
||||||
|
// Ensure the PfmFile is an appropriate size.
|
||||||
|
int x_size = do_get_expected_mipmap_x_size(cdata, n);
|
||||||
|
int y_size = do_get_expected_mipmap_y_size(cdata, n);
|
||||||
|
if (pfm.get_x_size() != x_size ||
|
||||||
|
pfm.get_y_size() != y_size) {
|
||||||
|
gobj_cat.info()
|
||||||
|
<< "Automatically rescaling " << name;
|
||||||
|
if (n != 0) {
|
||||||
|
gobj_cat.info(false)
|
||||||
|
<< " mipmap level " << n;
|
||||||
|
}
|
||||||
|
gobj_cat.info(false)
|
||||||
|
<< " from " << pfm.get_x_size() << " by "
|
||||||
|
<< pfm.get_y_size() << " to " << x_size << " by "
|
||||||
|
<< y_size << "\n";
|
||||||
|
|
||||||
|
PfmFile scaled(pfm);
|
||||||
|
scaled.resize(x_size, y_size);
|
||||||
|
Thread::consider_yield();
|
||||||
|
|
||||||
|
convert_from_pfm(cdata->_ram_images[n]._image,
|
||||||
|
do_get_expected_ram_mipmap_page_size(cdata, n), z,
|
||||||
|
scaled, cdata->_num_components, cdata->_component_width);
|
||||||
|
} else {
|
||||||
|
// Now copy the pixel data from the PfmFile into our internal
|
||||||
|
// cdata->_image component.
|
||||||
|
convert_from_pfm(cdata->_ram_images[n]._image,
|
||||||
|
do_get_expected_ram_mipmap_page_size(cdata, n), z,
|
||||||
|
pfm, cdata->_num_components, cdata->_component_width);
|
||||||
|
}
|
||||||
|
Thread::consider_yield();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: Texture::do_read_txo_file
|
// Function: Texture::do_read_txo_file
|
||||||
// Access: Protected
|
// Access: Protected
|
||||||
@ -3691,16 +3799,29 @@ do_write_one(CData *cdata, const Filename &fullpath, int z, int n) {
|
|||||||
|
|
||||||
nassertr(cdata->_ram_image_compression == CM_off, false);
|
nassertr(cdata->_ram_image_compression == CM_off, false);
|
||||||
|
|
||||||
|
bool success;
|
||||||
|
if (cdata->_component_type == T_float) {
|
||||||
|
// Writing a floating-point texture.
|
||||||
|
PfmFile pfm;
|
||||||
|
if (!do_store_one(cdata, pfm, z, n)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
success = pfm.write(fullpath);
|
||||||
|
} else {
|
||||||
|
// Writing a normal, integer texture.
|
||||||
PNMImage pnmimage;
|
PNMImage pnmimage;
|
||||||
if (!do_store_one(cdata, pnmimage, z, n)) {
|
if (!do_store_one(cdata, pnmimage, z, n)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
success = pnmimage.write(fullpath);
|
||||||
|
}
|
||||||
|
|
||||||
if (!pnmimage.write(fullpath)) {
|
if (!success) {
|
||||||
gobj_cat.error()
|
gobj_cat.error()
|
||||||
<< "Texture::write() - couldn't write: " << fullpath << endl;
|
<< "Texture::write() - couldn't write: " << fullpath << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3730,6 +3851,32 @@ do_store_one(CData *cdata, PNMImage &pnmimage, int z, int n) {
|
|||||||
do_get_ram_mipmap_page_size(cdata, n), z);
|
do_get_ram_mipmap_page_size(cdata, n), z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Texture::do_store_one
|
||||||
|
// Access: Protected
|
||||||
|
// Description: Internal method to copy a page and/or mipmap level to
|
||||||
|
// a PfmFile.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool Texture::
|
||||||
|
do_store_one(CData *cdata, PfmFile &pfm, int z, int n) {
|
||||||
|
// First, reload the ram image if necessary.
|
||||||
|
do_get_uncompressed_ram_image(cdata);
|
||||||
|
|
||||||
|
if (!do_has_ram_mipmap_image(cdata, n)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nassertr(z >= 0 && z < do_get_expected_mipmap_num_pages(cdata, n), false);
|
||||||
|
nassertr(cdata->_ram_image_compression == CM_off, false);
|
||||||
|
|
||||||
|
return convert_to_pfm(pfm,
|
||||||
|
do_get_expected_mipmap_x_size(cdata, n),
|
||||||
|
do_get_expected_mipmap_y_size(cdata, n),
|
||||||
|
cdata->_num_components, cdata->_component_width,
|
||||||
|
cdata->_ram_images[n]._image,
|
||||||
|
do_get_ram_mipmap_page_size(cdata, n), z);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: Texture::do_write_txo_file
|
// Function: Texture::do_write_txo_file
|
||||||
// Access: Private
|
// Access: Private
|
||||||
@ -4497,14 +4644,18 @@ bool Texture::
|
|||||||
do_reconsider_image_properties(CData *cdata, int x_size, int y_size, int num_components,
|
do_reconsider_image_properties(CData *cdata, int x_size, int y_size, int num_components,
|
||||||
Texture::ComponentType component_type, int z,
|
Texture::ComponentType component_type, int z,
|
||||||
const LoaderOptions &options) {
|
const LoaderOptions &options) {
|
||||||
if (!cdata->_loaded_from_image || num_components != cdata->_num_components) {
|
if (!cdata->_loaded_from_image || num_components != cdata->_num_components || component_type != cdata->_component_type) {
|
||||||
// Come up with a default format based on the number of channels.
|
// Come up with a default format based on the number of channels.
|
||||||
// But only do this the first time the file is loaded, or if the
|
// But only do this the first time the file is loaded, or if the
|
||||||
// number of channels in the image changes on subsequent loads.
|
// number of channels in the image changes on subsequent loads.
|
||||||
|
|
||||||
switch (num_components) {
|
switch (num_components) {
|
||||||
case 1:
|
case 1:
|
||||||
|
if (component_type == T_float) {
|
||||||
|
cdata->_format = F_depth_component;
|
||||||
|
} else {
|
||||||
cdata->_format = F_luminance;
|
cdata->_format = F_luminance;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
@ -5711,6 +5862,35 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, int z,
|
|||||||
nassertv(p == &image[idx] + page_size);
|
nassertv(p == &image[idx] + page_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Texture::convert_from_pfm
|
||||||
|
// Access: Private, Static
|
||||||
|
// Description: Internal method to convert pixel data from the
|
||||||
|
// indicated PfmFile into the given ram_image.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void Texture::
|
||||||
|
convert_from_pfm(PTA_uchar &image, size_t page_size, int z,
|
||||||
|
const PfmFile &pfm, int num_components, int component_width) {
|
||||||
|
nassertv(component_width == 4); // Currently only PN_float32 is expected.
|
||||||
|
int x_size = pfm.get_x_size();
|
||||||
|
int y_size = pfm.get_y_size();
|
||||||
|
|
||||||
|
int idx = page_size * z;
|
||||||
|
nassertv(idx + page_size <= image.size());
|
||||||
|
PN_float32 *p = (PN_float32 *)&image[idx];
|
||||||
|
|
||||||
|
for (int j = y_size-1; j >= 0; j--) {
|
||||||
|
for (int i = 0; i < x_size; i++) {
|
||||||
|
for (int c = 0; c < num_components; ++c) {
|
||||||
|
*p = pfm.get_component(i, j, c);
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nassertv((unsigned char *)p == &image[idx] + page_size);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: Texture::convert_to_pnmimage
|
// Function: Texture::convert_to_pnmimage
|
||||||
// Access: Private, Static
|
// Access: Private, Static
|
||||||
@ -5769,6 +5949,36 @@ convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Texture::convert_to_pfm
|
||||||
|
// Access: Private, Static
|
||||||
|
// Description: Internal method to convert pixel data to the
|
||||||
|
// indicated PfmFile from the given ram_image.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool Texture::
|
||||||
|
convert_to_pfm(PfmFile &pfm, int x_size, int y_size,
|
||||||
|
int num_components, int component_width,
|
||||||
|
CPTA_uchar image, size_t page_size, int z) {
|
||||||
|
nassertr(component_width == 4, false); // Currently only PN_float32 is expected.
|
||||||
|
pfm.clear(x_size, y_size, num_components);
|
||||||
|
|
||||||
|
int idx = page_size * z;
|
||||||
|
nassertr(idx + page_size <= image.size(), false);
|
||||||
|
const PN_float32 *p = (const PN_float32 *)&image[idx];
|
||||||
|
|
||||||
|
for (int j = y_size-1; j >= 0; j--) {
|
||||||
|
for (int i = 0; i < x_size; i++) {
|
||||||
|
for (int c = 0; c < num_components; ++c) {
|
||||||
|
pfm.set_component(i, j, c, *p);
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nassertr((unsigned char *)p == &image[idx] + page_size, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: Texture::read_dds_level_bgr8
|
// Function: Texture::read_dds_level_bgr8
|
||||||
// Access: Private, Static
|
// Access: Private, Static
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "pipelineCycler.h"
|
#include "pipelineCycler.h"
|
||||||
|
|
||||||
class PNMImage;
|
class PNMImage;
|
||||||
|
class PfmFile;
|
||||||
class TextureContext;
|
class TextureContext;
|
||||||
class FactoryParams;
|
class FactoryParams;
|
||||||
class PreparedGraphicsObjects;
|
class PreparedGraphicsObjects;
|
||||||
@ -541,6 +542,9 @@ protected:
|
|||||||
virtual bool do_load_one(CData *cdata,
|
virtual bool do_load_one(CData *cdata,
|
||||||
const PNMImage &pnmimage, const string &name,
|
const PNMImage &pnmimage, const string &name,
|
||||||
int z, int n, const LoaderOptions &options);
|
int z, int n, const LoaderOptions &options);
|
||||||
|
virtual bool do_load_one(CData *cdata,
|
||||||
|
const PfmFile &pfm, const string &name,
|
||||||
|
int z, int n, const LoaderOptions &options);
|
||||||
bool do_read_txo_file(CData *cdata, const Filename &fullpath);
|
bool do_read_txo_file(CData *cdata, const Filename &fullpath);
|
||||||
bool do_read_txo(CData *cdata, istream &in, const string &filename);
|
bool do_read_txo(CData *cdata, istream &in, const string &filename);
|
||||||
bool do_read_dds_file(CData *cdata, const Filename &fullpath, bool header_only);
|
bool do_read_dds_file(CData *cdata, const Filename &fullpath, bool header_only);
|
||||||
@ -550,6 +554,7 @@ protected:
|
|||||||
bool write_pages, bool write_mipmaps);
|
bool write_pages, bool write_mipmaps);
|
||||||
bool do_write_one(CData *cdata, const Filename &fullpath, int z, int n);
|
bool do_write_one(CData *cdata, const Filename &fullpath, int z, int n);
|
||||||
bool do_store_one(CData *cdata, PNMImage &pnmimage, int z, int n);
|
bool do_store_one(CData *cdata, PNMImage &pnmimage, int z, int n);
|
||||||
|
bool do_store_one(CData *cdata, PfmFile &pfm, int z, int n);
|
||||||
bool do_write_txo_file(const CData *cdata, const Filename &fullpath) const;
|
bool do_write_txo_file(const CData *cdata, const Filename &fullpath) const;
|
||||||
bool do_write_txo(const CData *cdata, ostream &out, const string &filename) const;
|
bool do_write_txo(const CData *cdata, ostream &out, const string &filename) const;
|
||||||
|
|
||||||
@ -656,10 +661,17 @@ private:
|
|||||||
static void convert_from_pnmimage(PTA_uchar &image, size_t page_size,
|
static void convert_from_pnmimage(PTA_uchar &image, size_t page_size,
|
||||||
int z, const PNMImage &pnmimage,
|
int z, const PNMImage &pnmimage,
|
||||||
int num_components, int component_width);
|
int num_components, int component_width);
|
||||||
|
static void convert_from_pfm(PTA_uchar &image, size_t page_size,
|
||||||
|
int z, const PfmFile &pfm,
|
||||||
|
int num_components, int component_width);
|
||||||
static bool convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size,
|
static bool convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size,
|
||||||
int num_components, int component_width,
|
int num_components, int component_width,
|
||||||
CPTA_uchar image, size_t page_size,
|
CPTA_uchar image, size_t page_size,
|
||||||
int z);
|
int z);
|
||||||
|
static bool convert_to_pfm(PfmFile &pfm, int x_size, int y_size,
|
||||||
|
int num_components, int component_width,
|
||||||
|
CPTA_uchar image, size_t page_size,
|
||||||
|
int z);
|
||||||
static PTA_uchar read_dds_level_bgr8(Texture *tex, CData *cdata, const DDSHeader &header,
|
static PTA_uchar read_dds_level_bgr8(Texture *tex, CData *cdata, const DDSHeader &header,
|
||||||
int n, istream &in);
|
int n, istream &in);
|
||||||
static PTA_uchar read_dds_level_rgb8(Texture *tex, CData *cdata, const DDSHeader &header,
|
static PTA_uchar read_dds_level_rgb8(Texture *tex, CData *cdata, const DDSHeader &header,
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#define SOURCES \
|
#define SOURCES \
|
||||||
config_pnmimage.h \
|
config_pnmimage.h \
|
||||||
pfmFile.I pfmFile.h \
|
pfmFile.I pfmFile.h \
|
||||||
pnmFileTypePfm.h \
|
|
||||||
pnmbitio.h \
|
pnmbitio.h \
|
||||||
pnmBrush.h pnmBrush.I \
|
pnmBrush.h pnmBrush.I \
|
||||||
pnmFileType.h pnmFileTypeRegistry.h pnmImage.I \
|
pnmFileType.h pnmFileTypeRegistry.h pnmImage.I \
|
||||||
@ -25,7 +24,6 @@
|
|||||||
#define INCLUDED_SOURCES \
|
#define INCLUDED_SOURCES \
|
||||||
config_pnmimage.cxx \
|
config_pnmimage.cxx \
|
||||||
pfmFile.cxx \
|
pfmFile.cxx \
|
||||||
pnmFileTypePfm.cxx \
|
|
||||||
pnm-image-filter.cxx \
|
pnm-image-filter.cxx \
|
||||||
pnmbitio.cxx \
|
pnmbitio.cxx \
|
||||||
pnmBrush.cxx \
|
pnmBrush.cxx \
|
||||||
@ -38,7 +36,6 @@
|
|||||||
#define INSTALL_HEADERS \
|
#define INSTALL_HEADERS \
|
||||||
config_pnmimage.h \
|
config_pnmimage.h \
|
||||||
pfmFile.I pfmFile.h \
|
pfmFile.I pfmFile.h \
|
||||||
pnmFileTypePfm.h \
|
|
||||||
pnmBrush.h pnmBrush.I \
|
pnmBrush.h pnmBrush.I \
|
||||||
pnmFileType.h pnmFileTypeRegistry.h pnmImage.I \
|
pnmFileType.h pnmFileTypeRegistry.h pnmImage.I \
|
||||||
pnmImage.h pnmImageHeader.I pnmImageHeader.h \
|
pnmImage.h pnmImageHeader.I pnmImageHeader.h \
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
#include "config_pnmimage.h"
|
#include "config_pnmimage.h"
|
||||||
#include "pnmFileType.h"
|
#include "pnmFileType.h"
|
||||||
#include "pnmFileTypePfm.h"
|
|
||||||
#include "pnmFileTypeRegistry.h"
|
#include "pnmFileTypeRegistry.h"
|
||||||
|
|
||||||
#include "dconfig.h"
|
#include "dconfig.h"
|
||||||
@ -66,9 +65,4 @@ init_libpnmimage() {
|
|||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
PNMFileType::init_type();
|
PNMFileType::init_type();
|
||||||
|
|
||||||
PNMFileTypeRegistry *tr = PNMFileTypeRegistry::get_global_ptr();
|
|
||||||
PNMFileTypePfm::init_type();
|
|
||||||
PNMFileTypePfm::register_with_read_factory();
|
|
||||||
tr->register_type(new PNMFileTypePfm);
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "config_pnmimage.cxx"
|
#include "config_pnmimage.cxx"
|
||||||
#include "pfmFile.cxx"
|
#include "pfmFile.cxx"
|
||||||
#include "pnmFileTypePfm.cxx"
|
|
||||||
#include "pnm-image-filter.cxx"
|
#include "pnm-image-filter.cxx"
|
||||||
#include "pnmbitio.cxx"
|
#include "pnmbitio.cxx"
|
||||||
#include "pnmBrush.cxx"
|
#include "pnmBrush.cxx"
|
||||||
|
@ -23,26 +23,6 @@ is_valid() const {
|
|||||||
return _num_channels != 0 && (_x_size * _y_size * _num_channels <= (int)_table.size());
|
return _num_channels != 0 && (_x_size * _y_size * _num_channels <= (int)_table.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: PfmFile::get_x_size
|
|
||||||
// Access: Published
|
|
||||||
// Description:
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
INLINE int PfmFile::
|
|
||||||
get_x_size() const {
|
|
||||||
return _x_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: PfmFile::get_y_size
|
|
||||||
// Access: Published
|
|
||||||
// Description:
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
INLINE int PfmFile::
|
|
||||||
get_y_size() const {
|
|
||||||
return _y_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PfmFile::get_scale
|
// Function: PfmFile::get_scale
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -55,18 +35,14 @@ get_scale() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PfmFile::get_num_channels
|
// Function: PfmFile::set_scale
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: A pfm file can be either 1-channel
|
// Description: The "scale" is reported in the pfm header and is
|
||||||
// (get_num_channels() == 1) or 3-channel
|
// probably meaningless.
|
||||||
// (get_num_channels() == 3). In the case of a
|
|
||||||
// 1-channel file, the values can be found in the x
|
|
||||||
// component of each point, and the y and z components
|
|
||||||
// are unused.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE int PfmFile::
|
INLINE void PfmFile::
|
||||||
get_num_channels() const {
|
set_scale(PN_float32 scale) {
|
||||||
return _num_channels;
|
_scale = scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -82,6 +58,34 @@ has_point(int x, int y) const {
|
|||||||
return _has_point(this, x, y);
|
return _has_point(this, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PfmFile::get_component
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the cth component of the point value at the
|
||||||
|
// indicated point.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE PN_float32 PfmFile::
|
||||||
|
get_component(int x, int y, int c) const {
|
||||||
|
nassertr(x >= 0 && x < _x_size &&
|
||||||
|
y >= 0 && y < _y_size &&
|
||||||
|
c >= 0 && c < _num_channels, 0.0f);
|
||||||
|
return _table[(y * _x_size + x) * _num_channels + c];
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PfmFile::set_component
|
||||||
|
// Access: Published
|
||||||
|
// Description: Replaces the cth component of the point value at the
|
||||||
|
// indicated point.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void PfmFile::
|
||||||
|
set_component(int x, int y, int c, PN_float32 value) {
|
||||||
|
nassertv(x >= 0 && x < _x_size &&
|
||||||
|
y >= 0 && y < _y_size &&
|
||||||
|
c >= 0 && c < _num_channels);
|
||||||
|
_table[(y * _x_size + x) * _num_channels + c] = value;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PfmFile::get_point1
|
// Function: PfmFile::get_point1
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -90,8 +94,8 @@ has_point(int x, int y) const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE PN_float32 PfmFile::
|
INLINE PN_float32 PfmFile::
|
||||||
get_point1(int x, int y) const {
|
get_point1(int x, int y) const {
|
||||||
nassertr(x >= 0 && x < _x_size, 0.0);
|
nassertr(x >= 0 && x < _x_size &&
|
||||||
nassertr(y >= 0 && y < _y_size, 0.0);
|
y >= 0 && y < _y_size, 0.0);
|
||||||
return _table[(y * _x_size + x) * _num_channels];
|
return _table[(y * _x_size + x) * _num_channels];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,8 +108,8 @@ get_point1(int x, int y) const {
|
|||||||
INLINE void PfmFile::
|
INLINE void PfmFile::
|
||||||
set_point1(int x, int y, PN_float32 point) {
|
set_point1(int x, int y, PN_float32 point) {
|
||||||
nassertv(!cnan(point));
|
nassertv(!cnan(point));
|
||||||
nassertv(x >= 0 && x < _x_size);
|
nassertv(x >= 0 && x < _x_size &&
|
||||||
nassertv(y >= 0 && y < _y_size);
|
y >= 0 && y < _y_size);
|
||||||
_table[(y * _x_size + x) * _num_channels] = point;
|
_table[(y * _x_size + x) * _num_channels] = point;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,8 +122,8 @@ set_point1(int x, int y, PN_float32 point) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE const LPoint3f &PfmFile::
|
INLINE const LPoint3f &PfmFile::
|
||||||
get_point(int x, int y) const {
|
get_point(int x, int y) const {
|
||||||
nassertr(x >= 0 && x < _x_size, LPoint3f::zero());
|
nassertr(x >= 0 && x < _x_size &&
|
||||||
nassertr(y >= 0 && y < _y_size, LPoint3f::zero());
|
y >= 0 && y < _y_size, LPoint3f::zero());
|
||||||
return *(LPoint3f *)&_table[(y * _x_size + x) * _num_channels];
|
return *(LPoint3f *)&_table[(y * _x_size + x) * _num_channels];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,8 +137,8 @@ get_point(int x, int y) const {
|
|||||||
INLINE void PfmFile::
|
INLINE void PfmFile::
|
||||||
set_point(int x, int y, const LVecBase3f &point) {
|
set_point(int x, int y, const LVecBase3f &point) {
|
||||||
nassertv(!point.is_nan());
|
nassertv(!point.is_nan());
|
||||||
nassertv(x >= 0 && x < _x_size);
|
nassertv(x >= 0 && x < _x_size &&
|
||||||
nassertv(y >= 0 && y < _y_size);
|
y >= 0 && y < _y_size);
|
||||||
switch (_num_channels) {
|
switch (_num_channels) {
|
||||||
case 1:
|
case 1:
|
||||||
_table[(y * _x_size + x)] = point[0];
|
_table[(y * _x_size + x)] = point[0];
|
||||||
@ -169,8 +173,8 @@ INLINE LPoint3f &PfmFile::
|
|||||||
modify_point(int x, int y) {
|
modify_point(int x, int y) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
static LPoint3f dummy_value = LPoint3f::zero();
|
static LPoint3f dummy_value = LPoint3f::zero();
|
||||||
nassertr(x >= 0 && x < _x_size, dummy_value);
|
nassertr(x >= 0 && x < _x_size &&
|
||||||
nassertr(y >= 0 && y < _y_size, dummy_value);
|
y >= 0 && y < _y_size, dummy_value);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return *(LPoint3f *)&_table[(y * _x_size + x) * _num_channels];
|
return *(LPoint3f *)&_table[(y * _x_size + x) * _num_channels];
|
||||||
@ -185,8 +189,8 @@ modify_point(int x, int y) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE const LPoint4f &PfmFile::
|
INLINE const LPoint4f &PfmFile::
|
||||||
get_point4(int x, int y) const {
|
get_point4(int x, int y) const {
|
||||||
nassertr(x >= 0 && x < _x_size, LPoint4f::zero());
|
nassertr(x >= 0 && x < _x_size &&
|
||||||
nassertr(y >= 0 && y < _y_size, LPoint4f::zero());
|
y >= 0 && y < _y_size, LPoint4f::zero());
|
||||||
return *(LPoint4f *)&_table[(y * _x_size + x) * _num_channels];
|
return *(LPoint4f *)&_table[(y * _x_size + x) * _num_channels];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,8 +204,8 @@ get_point4(int x, int y) const {
|
|||||||
INLINE void PfmFile::
|
INLINE void PfmFile::
|
||||||
set_point4(int x, int y, const LVecBase4f &point) {
|
set_point4(int x, int y, const LVecBase4f &point) {
|
||||||
nassertv(!point.is_nan());
|
nassertv(!point.is_nan());
|
||||||
nassertv(x >= 0 && x < _x_size);
|
nassertv(x >= 0 && x < _x_size &&
|
||||||
nassertv(y >= 0 && y < _y_size);
|
y >= 0 && y < _y_size);
|
||||||
switch (_num_channels) {
|
switch (_num_channels) {
|
||||||
case 1:
|
case 1:
|
||||||
_table[(y * _x_size + x)] = point[0];
|
_table[(y * _x_size + x)] = point[0];
|
||||||
@ -239,8 +243,8 @@ INLINE LPoint4f &PfmFile::
|
|||||||
modify_point4(int x, int y) {
|
modify_point4(int x, int y) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
static LPoint4f dummy_value = LPoint4f::zero();
|
static LPoint4f dummy_value = LPoint4f::zero();
|
||||||
nassertr(x >= 0 && x < _x_size, dummy_value);
|
nassertr(x >= 0 && x < _x_size &&
|
||||||
nassertr(y >= 0 && y < _y_size, dummy_value);
|
y >= 0 && y < _y_size, dummy_value);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return *(LPoint4f *)&_table[(y * _x_size + x) * _num_channels];
|
return *(LPoint4f *)&_table[(y * _x_size + x) * _num_channels];
|
||||||
@ -517,3 +521,30 @@ INLINE bool PfmFile::
|
|||||||
get_vis_2d() const {
|
get_vis_2d() const {
|
||||||
return _vis_2d;
|
return _vis_2d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PfmFile::get_table
|
||||||
|
// Access: Public
|
||||||
|
// Description: This is a very low-level function that returns a
|
||||||
|
// read-only reference to the internal table of
|
||||||
|
// floating-point numbers. Use this method at your own
|
||||||
|
// risk.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE const pvector<PN_float32> &PfmFile::
|
||||||
|
get_table() const {
|
||||||
|
return _table;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PfmFile::swap_table
|
||||||
|
// Access: Public
|
||||||
|
// Description: This is a very low-level function that completely
|
||||||
|
// exchanges the PfmFile's internal table of
|
||||||
|
// floating-point numbers with whatever you supply. The
|
||||||
|
// provided table must have an appropriate size. Use
|
||||||
|
// this method at your own risk.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void PfmFile::
|
||||||
|
swap_table(pvector<PN_float32> &table) {
|
||||||
|
_table.swap(table);
|
||||||
|
}
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "geomTriangles.h"
|
#include "geomTriangles.h"
|
||||||
#include "geomVertexWriter.h"
|
#include "geomVertexWriter.h"
|
||||||
#include "pnmImage.h"
|
#include "pnmImage.h"
|
||||||
|
#include "pnmReader.h"
|
||||||
#include "pnmWriter.h"
|
#include "pnmWriter.h"
|
||||||
#include "string_utils.h"
|
#include "string_utils.h"
|
||||||
#include "lens.h"
|
#include "lens.h"
|
||||||
@ -54,11 +55,9 @@ PfmFile() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PfmFile::
|
PfmFile::
|
||||||
PfmFile(const PfmFile ©) :
|
PfmFile(const PfmFile ©) :
|
||||||
|
PNMImageHeader(copy),
|
||||||
_table(copy._table),
|
_table(copy._table),
|
||||||
_x_size(copy._x_size),
|
|
||||||
_y_size(copy._y_size),
|
|
||||||
_scale(copy._scale),
|
_scale(copy._scale),
|
||||||
_num_channels(copy._num_channels),
|
|
||||||
_has_no_data_value(copy._has_no_data_value),
|
_has_no_data_value(copy._has_no_data_value),
|
||||||
_no_data_value(copy._no_data_value),
|
_no_data_value(copy._no_data_value),
|
||||||
_has_point(copy._has_point),
|
_has_point(copy._has_point),
|
||||||
@ -74,11 +73,9 @@ PfmFile(const PfmFile ©) :
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void PfmFile::
|
void PfmFile::
|
||||||
operator = (const PfmFile ©) {
|
operator = (const PfmFile ©) {
|
||||||
|
PNMImageHeader::operator = (copy);
|
||||||
_table = copy._table;
|
_table = copy._table;
|
||||||
_x_size = copy._x_size;
|
|
||||||
_y_size = copy._y_size;
|
|
||||||
_scale = copy._scale;
|
_scale = copy._scale;
|
||||||
_num_channels = copy._num_channels;
|
|
||||||
_has_no_data_value = copy._has_no_data_value;
|
_has_no_data_value = copy._has_no_data_value;
|
||||||
_no_data_value = copy._no_data_value;
|
_no_data_value = copy._no_data_value;
|
||||||
_has_point = copy._has_point;
|
_has_point = copy._has_point;
|
||||||
@ -108,7 +105,6 @@ clear() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void PfmFile::
|
void PfmFile::
|
||||||
clear(int x_size, int y_size, int num_channels) {
|
clear(int x_size, int y_size, int num_channels) {
|
||||||
nassertv(num_channels == 1 || num_channels == 3);
|
|
||||||
nassertv(x_size >= 0 && y_size >= 0);
|
nassertv(x_size >= 0 && y_size >= 0);
|
||||||
_x_size = x_size;
|
_x_size = x_size;
|
||||||
_y_size = y_size;
|
_y_size = y_size;
|
||||||
@ -172,108 +168,49 @@ read(const Filename &fullpath) {
|
|||||||
// to a floating-point type.
|
// to a floating-point type.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool PfmFile::
|
bool PfmFile::
|
||||||
read(istream &in, const Filename &fullpath, const string &magic_number) {
|
read(istream &in, const Filename &fullpath) {
|
||||||
|
PNMReader *reader = make_reader(&in, false, fullpath);
|
||||||
|
if (reader == (PNMReader *)NULL) {
|
||||||
|
clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return read(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PfmFile::read
|
||||||
|
// Access: Published
|
||||||
|
// Description: Reads the PFM data using the indicated PNMReader.
|
||||||
|
//
|
||||||
|
// The PNMReader is always deleted upon completion,
|
||||||
|
// whether successful or not.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool PfmFile::
|
||||||
|
read(PNMReader *reader) {
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
string identifier = magic_number;
|
if (reader == NULL) {
|
||||||
PNMImageHeader::read_magic_number(&in, identifier, 2);
|
|
||||||
|
|
||||||
if (identifier == "pf") {
|
|
||||||
// In this case, we're probably reading a special-extension
|
|
||||||
// 4-channel pfm file, and we need a four-byte magic number to
|
|
||||||
// confirm this and fully identify the file format.
|
|
||||||
PNMImageHeader::read_magic_number(&in, identifier, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (identifier == "PF") {
|
|
||||||
_num_channels = 3;
|
|
||||||
|
|
||||||
} else if (identifier == "Pf") {
|
|
||||||
_num_channels = 1;
|
|
||||||
|
|
||||||
} else if (identifier == "pf4c") {
|
|
||||||
_num_channels = 4;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Not a PFM file. Maybe it's a more conventional image file that
|
|
||||||
// we can read into a PFM.
|
|
||||||
PNMImage pnm;
|
|
||||||
PNMReader *reader = pnm.make_reader
|
|
||||||
(&in, false, fullpath, identifier, NULL, false);
|
|
||||||
if (reader == (PNMReader *)NULL) {
|
|
||||||
pnmimage_cat.error()
|
|
||||||
<< "Not a PFM file or known image file type: " << fullpath << "\n";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!reader->is_valid()) {
|
||||||
|
delete reader;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reader->is_floating_point()) {
|
||||||
|
// Not a floating-point file. Quietly convert it.
|
||||||
|
PNMImage pnm;
|
||||||
if (!pnm.read(reader)) {
|
if (!pnm.read(reader)) {
|
||||||
pnmimage_cat.error()
|
|
||||||
<< "Invalid image file: " << fullpath << "\n";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return load(pnm);
|
return load(pnm);
|
||||||
}
|
}
|
||||||
|
|
||||||
int width, height;
|
bool success = reader->read_pfm(*this);
|
||||||
PN_float32 scale;
|
delete reader;
|
||||||
in >> width >> height >> scale;
|
return success;
|
||||||
if (!in) {
|
|
||||||
pnmimage_cat.error()
|
|
||||||
<< "Error parsing PFM header: " << fullpath << "\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip the last newline/whitespace character before the raw data
|
|
||||||
// begins.
|
|
||||||
in.get();
|
|
||||||
|
|
||||||
bool little_endian = false;
|
|
||||||
if (scale < 0) {
|
|
||||||
scale = -scale;
|
|
||||||
little_endian = true;
|
|
||||||
}
|
|
||||||
if (pfm_force_littleendian) {
|
|
||||||
little_endian = true;
|
|
||||||
}
|
|
||||||
if (pfm_reverse_dimensions) {
|
|
||||||
int t = width;
|
|
||||||
width = height;
|
|
||||||
height = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
_x_size = width;
|
|
||||||
_y_size = height;
|
|
||||||
_scale = scale;
|
|
||||||
|
|
||||||
// So far, so good. Now read the data.
|
|
||||||
int size = _x_size * _y_size * _num_channels;
|
|
||||||
|
|
||||||
// We allocate a little bit bigger to allow safe overflow: you can
|
|
||||||
// call get_point3() or get_point4() on the last point of a 1- or
|
|
||||||
// 3-channel image.
|
|
||||||
_table.insert(_table.end(), size + 4, (PN_float32)0.0);
|
|
||||||
|
|
||||||
in.read((char *)&_table[0], sizeof(PN_float32) * size);
|
|
||||||
if (in.fail() && !in.eof()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now we may have to endian-reverse the data.
|
|
||||||
#ifdef WORDS_BIGENDIAN
|
|
||||||
bool endian_reversed = little_endian;
|
|
||||||
#else
|
|
||||||
bool endian_reversed = !little_endian;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (endian_reversed) {
|
|
||||||
for (int ti = 0; ti < size; ++ti) {
|
|
||||||
ReversedNumericData nd(&_table[ti], sizeof(PN_float32));
|
|
||||||
nd.store_value(&_table[ti], sizeof(PN_float32));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -335,45 +272,56 @@ write(const Filename &fullpath) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool PfmFile::
|
bool PfmFile::
|
||||||
write(ostream &out, const Filename &fullpath) {
|
write(ostream &out, const Filename &fullpath) {
|
||||||
nassertr(is_valid(), false);
|
if (!is_valid()) {
|
||||||
|
|
||||||
switch (_num_channels) {
|
|
||||||
case 1:
|
|
||||||
out << "Pf\n";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
out << "PF\n";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
out << "pf4c\n";
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
nassertr(false, false);
|
|
||||||
}
|
|
||||||
out << _x_size << " " << _y_size << "\n";
|
|
||||||
|
|
||||||
PN_float32 scale = cabs(_scale);
|
|
||||||
if (scale == 0.0f) {
|
|
||||||
scale = 1.0f;
|
|
||||||
}
|
|
||||||
#ifndef WORDS_BIGENDIAN
|
|
||||||
// Little-endian computers must write a negative scale to indicate
|
|
||||||
// the little-endian nature of the output.
|
|
||||||
scale = -scale;
|
|
||||||
#endif
|
|
||||||
out << scale << "\n";
|
|
||||||
|
|
||||||
int size = _x_size * _y_size * _num_channels;
|
|
||||||
out.write((const char *)&_table[0], sizeof(PN_float32) * size);
|
|
||||||
|
|
||||||
if (out.fail()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
nassertr(sizeof(PN_float32) == 4, false);
|
|
||||||
return true;
|
PNMWriter *writer = make_writer(fullpath);
|
||||||
|
if (writer == (PNMWriter *)NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return write(writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PfmFile::write
|
||||||
|
// Access: Published
|
||||||
|
// Description: Writes the PFM data using the indicated PNMWriter.
|
||||||
|
//
|
||||||
|
// The PNMWriter is always deleted upon completion,
|
||||||
|
// whether successful or not.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool PfmFile::
|
||||||
|
write(PNMWriter *writer) {
|
||||||
|
if (writer == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_valid()) {
|
||||||
|
delete writer;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer->copy_header_from(*this);
|
||||||
|
|
||||||
|
if (!writer->supports_floating_point()) {
|
||||||
|
// Hmm, it's an integer file type. Convert it from the
|
||||||
|
// floating-point data we have.
|
||||||
|
PNMImage pnmimage;
|
||||||
|
if (!store(pnmimage)) {
|
||||||
|
delete writer;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
writer->copy_header_from(pnmimage);
|
||||||
|
bool success = writer->write_data(pnmimage.get_array(), pnmimage.get_alpha_array());
|
||||||
|
delete writer;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = writer->write_pfm(*this);
|
||||||
|
delete writer;
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -1436,6 +1384,17 @@ generate_vis_mesh(MeshFace face) const {
|
|||||||
return NodePath(gnode);
|
return NodePath(gnode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PfmFile::output
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void PfmFile::
|
||||||
|
output(ostream &out) const {
|
||||||
|
out << "floating-point image: " << _x_size << " by " << _y_size << " pixels, "
|
||||||
|
<< _num_channels << " channels.";
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PfmFile::make_vis_mesh_geom
|
// Function: PfmFile::make_vis_mesh_geom
|
||||||
// Access: Private
|
// Access: Private
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#define PFMFILE_H
|
#define PFMFILE_H
|
||||||
|
|
||||||
#include "pandabase.h"
|
#include "pandabase.h"
|
||||||
|
#include "pnmImageHeader.h"
|
||||||
#include "luse.h"
|
#include "luse.h"
|
||||||
#include "nodePath.h"
|
#include "nodePath.h"
|
||||||
#include "boundingHexahedron.h"
|
#include "boundingHexahedron.h"
|
||||||
@ -25,6 +26,8 @@
|
|||||||
class GeomNode;
|
class GeomNode;
|
||||||
class Lens;
|
class Lens;
|
||||||
class PNMImage;
|
class PNMImage;
|
||||||
|
class PNMReader;
|
||||||
|
class PNMWriter;
|
||||||
class GeomVertexWriter;
|
class GeomVertexWriter;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -33,7 +36,7 @@ class GeomVertexWriter;
|
|||||||
// numbers, either 3-component or 1-component, or with a
|
// numbers, either 3-component or 1-component, or with a
|
||||||
// special extension, 4-component.
|
// special extension, 4-component.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDA_PNMIMAGE PfmFile {
|
class EXPCL_PANDA_PNMIMAGE PfmFile : public PNMImageHeader {
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
PfmFile();
|
PfmFile();
|
||||||
PfmFile(const PfmFile ©);
|
PfmFile(const PfmFile ©);
|
||||||
@ -43,22 +46,23 @@ PUBLISHED:
|
|||||||
void clear(int x_size, int y_size, int num_channels);
|
void clear(int x_size, int y_size, int num_channels);
|
||||||
|
|
||||||
BLOCKING bool read(const Filename &fullpath);
|
BLOCKING bool read(const Filename &fullpath);
|
||||||
BLOCKING bool read(istream &in, const Filename &fullpath = Filename(),
|
BLOCKING bool read(istream &in, const Filename &fullpath = Filename());
|
||||||
const string &magic_number = string());
|
BLOCKING bool read(PNMReader *reader);
|
||||||
BLOCKING bool write(const Filename &fullpath);
|
BLOCKING bool write(const Filename &fullpath);
|
||||||
BLOCKING bool write(ostream &out, const Filename &fullpath = Filename());
|
BLOCKING bool write(ostream &out, const Filename &fullpath = Filename());
|
||||||
|
BLOCKING bool write(PNMWriter *writer);
|
||||||
|
|
||||||
BLOCKING bool load(const PNMImage &pnmimage);
|
BLOCKING bool load(const PNMImage &pnmimage);
|
||||||
BLOCKING bool store(PNMImage &pnmimage) const;
|
BLOCKING bool store(PNMImage &pnmimage) const;
|
||||||
|
|
||||||
INLINE bool is_valid() const;
|
INLINE bool is_valid() const;
|
||||||
|
|
||||||
INLINE int get_x_size() const;
|
|
||||||
INLINE int get_y_size() const;
|
|
||||||
INLINE PN_float32 get_scale() const;
|
INLINE PN_float32 get_scale() const;
|
||||||
INLINE int get_num_channels() const;
|
INLINE void set_scale(PN_float32 scale);
|
||||||
|
|
||||||
INLINE bool has_point(int x, int y) const;
|
INLINE bool has_point(int x, int y) const;
|
||||||
|
INLINE PN_float32 get_component(int x, int y, int c) const;
|
||||||
|
INLINE void set_component(int x, int y, int c, PN_float32 value);
|
||||||
INLINE PN_float32 get_point1(int x, int y) const;
|
INLINE PN_float32 get_point1(int x, int y) const;
|
||||||
INLINE void set_point1(int x, int y, PN_float32 point);
|
INLINE void set_point1(int x, int y, PN_float32 point);
|
||||||
INLINE const LPoint3f &get_point(int x, int y) const;
|
INLINE const LPoint3f &get_point(int x, int y) const;
|
||||||
@ -131,6 +135,12 @@ PUBLISHED:
|
|||||||
};
|
};
|
||||||
BLOCKING NodePath generate_vis_mesh(MeshFace face = MF_front) const;
|
BLOCKING NodePath generate_vis_mesh(MeshFace face = MF_front) const;
|
||||||
|
|
||||||
|
void output(ostream &out) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
INLINE const pvector<PN_float32> &get_table() const;
|
||||||
|
INLINE void swap_table(pvector<PN_float32> &table);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void make_vis_mesh_geom(GeomNode *gnode, bool inverted) const;
|
void make_vis_mesh_geom(GeomNode *gnode, bool inverted) const;
|
||||||
|
|
||||||
@ -196,10 +206,7 @@ private:
|
|||||||
typedef pvector<PN_float32> Table;
|
typedef pvector<PN_float32> Table;
|
||||||
Table _table;
|
Table _table;
|
||||||
|
|
||||||
int _x_size;
|
|
||||||
int _y_size;
|
|
||||||
PN_float32 _scale;
|
PN_float32 _scale;
|
||||||
int _num_channels;
|
|
||||||
|
|
||||||
bool _has_no_data_value;
|
bool _has_no_data_value;
|
||||||
LPoint4f _no_data_value;
|
LPoint4f _no_data_value;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "pnmReader.h"
|
#include "pnmReader.h"
|
||||||
#include "pnmWriter.h"
|
#include "pnmWriter.h"
|
||||||
#include "pnmBrush.h"
|
#include "pnmBrush.h"
|
||||||
|
#include "pfmFile.h"
|
||||||
#include "config_pnmimage.h"
|
#include "config_pnmimage.h"
|
||||||
#include "perlinNoise2.h"
|
#include "perlinNoise2.h"
|
||||||
#include "stackedPerlinNoise2.h"
|
#include "stackedPerlinNoise2.h"
|
||||||
@ -307,6 +308,17 @@ read(PNMReader *reader) {
|
|||||||
|
|
||||||
copy_header_from(*reader);
|
copy_header_from(*reader);
|
||||||
|
|
||||||
|
if (reader->is_floating_point()) {
|
||||||
|
// Hmm, it's a floating-point file. Quietly convert it to integer.
|
||||||
|
PfmFile pfm;
|
||||||
|
if (!reader->read_pfm(pfm)) {
|
||||||
|
delete reader;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
delete reader;
|
||||||
|
return pfm.store(*this);
|
||||||
|
}
|
||||||
|
|
||||||
// We reassign y_size after reading because we might have read a
|
// We reassign y_size after reading because we might have read a
|
||||||
// truncated file.
|
// truncated file.
|
||||||
_y_size = reader->read_data(_array, _alpha);
|
_y_size = reader->read_data(_array, _alpha);
|
||||||
@ -400,6 +412,20 @@ write(PNMWriter *writer) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
writer->copy_header_from(*this);
|
writer->copy_header_from(*this);
|
||||||
|
|
||||||
|
if (!writer->supports_integer()) {
|
||||||
|
// Hmm, it's only a floating-point file type. Convert it from the
|
||||||
|
// integer data we have.
|
||||||
|
PfmFile pfm;
|
||||||
|
if (!pfm.load(*this)) {
|
||||||
|
delete writer;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool success = writer->write_pfm(pfm);
|
||||||
|
delete writer;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_grayscale() && !writer->supports_grayscale()) {
|
if (is_grayscale() && !writer->supports_grayscale()) {
|
||||||
// Copy the gray values to all channels to help out the writer.
|
// Copy the gray values to all channels to help out the writer.
|
||||||
for (int y = 0; y < get_y_size(); y++) {
|
for (int y = 0; y < get_y_size(); y++) {
|
||||||
|
@ -70,6 +70,30 @@ prepare_read() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PNMReader::is_floating_point
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description: Returns true if this PNMFileType represents a
|
||||||
|
// floating-point image type, false if it is a normal,
|
||||||
|
// integer type. If this returns true, read_pfm() is
|
||||||
|
// implemented instead of read_data().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool PNMReader::
|
||||||
|
is_floating_point() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PNMReader::read_pfm
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description: Reads floating-point data directly into the indicated
|
||||||
|
// PfmFile. Returns true on success, false on failure.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool PNMReader::
|
||||||
|
read_pfm(PfmFile &pfm) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PNMReader::read_data
|
// Function: PNMReader::read_data
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include "pandabase.h"
|
#include "pandabase.h"
|
||||||
|
|
||||||
#include "pnmImageHeader.h"
|
#include "pnmImageHeader.h"
|
||||||
|
class PfmFile;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : PNMReader
|
// Class : PNMReader
|
||||||
@ -39,6 +39,8 @@ public:
|
|||||||
INLINE PNMFileType *get_type() const;
|
INLINE PNMFileType *get_type() const;
|
||||||
|
|
||||||
virtual void prepare_read();
|
virtual void prepare_read();
|
||||||
|
virtual bool is_floating_point();
|
||||||
|
virtual bool read_pfm(PfmFile &pfm);
|
||||||
virtual int read_data(xel *array, xelval *alpha);
|
virtual int read_data(xel *array, xelval *alpha);
|
||||||
virtual bool supports_read_row() const;
|
virtual bool supports_read_row() const;
|
||||||
virtual bool read_row(xel *array, xelval *alpha, int x_size, int y_size);
|
virtual bool read_row(xel *array, xelval *alpha, int x_size, int y_size);
|
||||||
|
@ -28,6 +28,43 @@ PNMWriter::
|
|||||||
_file = (ostream *)NULL;
|
_file = (ostream *)NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PNMWriter::supports_floating_point
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description: Returns true if this PNMFileType can accept a
|
||||||
|
// floating-point image type, false if it can only
|
||||||
|
// accept a normal, integer type. If this returns true,
|
||||||
|
// write_pfm() is implemented.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool PNMWriter::
|
||||||
|
supports_floating_point() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PNMWriter::supports_integer
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description: Returns true if this PNMFileType can accept an
|
||||||
|
// integer image type, false if it can only
|
||||||
|
// accept a floating-point type. If this returns true,
|
||||||
|
// write_data() or write_row() is implemented.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool PNMWriter::
|
||||||
|
supports_integer() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PNMWriter::write_pfm
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description: Writes floating-point data from the indicated
|
||||||
|
// PfmFile. Returns true on success, false on failure.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool PNMWriter::
|
||||||
|
write_pfm(const PfmFile &pfm) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PNMWriter::write_data
|
// Function: PNMWriter::write_data
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "pandabase.h"
|
#include "pandabase.h"
|
||||||
|
|
||||||
#include "pnmImageHeader.h"
|
#include "pnmImageHeader.h"
|
||||||
|
class PfmFile;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : PNMWriter
|
// Class : PNMWriter
|
||||||
@ -48,6 +49,10 @@ public:
|
|||||||
|
|
||||||
INLINE void copy_header_from(const PNMImageHeader &header);
|
INLINE void copy_header_from(const PNMImageHeader &header);
|
||||||
|
|
||||||
|
virtual bool supports_floating_point();
|
||||||
|
virtual bool supports_integer();
|
||||||
|
virtual bool write_pfm(const PfmFile &pfm);
|
||||||
|
|
||||||
virtual int write_data(xel *array, xelval *alpha);
|
virtual int write_data(xel *array, xelval *alpha);
|
||||||
virtual bool supports_write_row() const;
|
virtual bool supports_write_row() const;
|
||||||
virtual bool supports_grayscale() const;
|
virtual bool supports_grayscale() const;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
pnmFileTypeIMG.h \
|
pnmFileTypeIMG.h \
|
||||||
pnmFileTypePNG.h \
|
pnmFileTypePNG.h \
|
||||||
pnmFileTypePNM.h \
|
pnmFileTypePNM.h \
|
||||||
|
pnmFileTypePfm.h \
|
||||||
pnmFileTypeSGI.h pnmFileTypeSoftImage.h \
|
pnmFileTypeSGI.h pnmFileTypeSoftImage.h \
|
||||||
pnmFileTypeTGA.h \
|
pnmFileTypeTGA.h \
|
||||||
pnmFileTypeTIFF.h \
|
pnmFileTypeTIFF.h \
|
||||||
@ -28,6 +29,7 @@
|
|||||||
pnmFileTypeJPG.cxx pnmFileTypeJPGReader.cxx pnmFileTypeJPGWriter.cxx \
|
pnmFileTypeJPG.cxx pnmFileTypeJPGReader.cxx pnmFileTypeJPGWriter.cxx \
|
||||||
pnmFileTypePNG.cxx \
|
pnmFileTypePNG.cxx \
|
||||||
pnmFileTypePNM.cxx \
|
pnmFileTypePNM.cxx \
|
||||||
|
pnmFileTypePfm.cxx \
|
||||||
pnmFileTypeSGI.cxx \
|
pnmFileTypeSGI.cxx \
|
||||||
pnmFileTypeSGIReader.cxx pnmFileTypeSGIWriter.cxx \
|
pnmFileTypeSGIReader.cxx pnmFileTypeSGIWriter.cxx \
|
||||||
pnmFileTypeSoftImage.cxx \
|
pnmFileTypeSoftImage.cxx \
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "pnmFileTypeJPG.h"
|
#include "pnmFileTypeJPG.h"
|
||||||
#include "pnmFileTypePNG.h"
|
#include "pnmFileTypePNG.h"
|
||||||
#include "pnmFileTypePNM.h"
|
#include "pnmFileTypePNM.h"
|
||||||
|
#include "pnmFileTypePfm.h"
|
||||||
#include "pnmFileTypeTIFF.h"
|
#include "pnmFileTypeTIFF.h"
|
||||||
#include "sgi.h"
|
#include "sgi.h"
|
||||||
|
|
||||||
@ -216,6 +217,10 @@ init_libpnmimagetypes() {
|
|||||||
tr->register_type(new PNMFileTypePNM);
|
tr->register_type(new PNMFileTypePNM);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
PNMFileTypePfm::init_type();
|
||||||
|
PNMFileTypePfm::register_with_read_factory();
|
||||||
|
tr->register_type(new PNMFileTypePfm);
|
||||||
|
|
||||||
#ifdef HAVE_JPEG
|
#ifdef HAVE_JPEG
|
||||||
PNMFileTypeJPG::init_type();
|
PNMFileTypeJPG::init_type();
|
||||||
PNMFileTypeJPG::register_with_read_factory();
|
PNMFileTypeJPG::register_with_read_factory();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "pnmFileTypePNG.cxx"
|
#include "pnmFileTypePNG.cxx"
|
||||||
#include "pnmFileTypeTIFF.cxx"
|
#include "pnmFileTypeTIFF.cxx"
|
||||||
#include "pnmFileTypePNM.cxx"
|
#include "pnmFileTypePNM.cxx"
|
||||||
|
#include "pnmFileTypePfm.cxx"
|
||||||
#include "pnmFileTypeSGI.cxx"
|
#include "pnmFileTypeSGI.cxx"
|
||||||
#include "pnmFileTypeSGIReader.cxx"
|
#include "pnmFileTypeSGIReader.cxx"
|
||||||
#include "pnmFileTypeSGIWriter.cxx"
|
#include "pnmFileTypeSGIWriter.cxx"
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "pnmFileTypePfm.h"
|
#include "pnmFileTypePfm.h"
|
||||||
|
#include "pfmFile.h"
|
||||||
#include "config_pnmimage.h"
|
#include "config_pnmimage.h"
|
||||||
|
|
||||||
#include "pnmFileTypeRegistry.h"
|
#include "pnmFileTypeRegistry.h"
|
||||||
@ -134,45 +135,115 @@ PNMFileTypePfm::Reader::
|
|||||||
Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) :
|
Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) :
|
||||||
PNMReader(type, file, owns_file)
|
PNMReader(type, file, owns_file)
|
||||||
{
|
{
|
||||||
PfmFile pfm;
|
read_magic_number(_file, magic_number, 2);
|
||||||
if (!pfm.read(*file, Filename(), magic_number)) {
|
|
||||||
|
if (magic_number == "pf") {
|
||||||
|
// In this case, we're probably reading a special-extension
|
||||||
|
// 4-channel pfm file, and we need a four-byte magic number to
|
||||||
|
// confirm this and fully identify the file format.
|
||||||
|
read_magic_number(_file, magic_number, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (magic_number == "PF") {
|
||||||
|
_num_channels = 3;
|
||||||
|
|
||||||
|
} else if (magic_number == "Pf") {
|
||||||
|
_num_channels = 1;
|
||||||
|
|
||||||
|
} else if (magic_number == "pf4c") {
|
||||||
|
// Special DRZ extension.
|
||||||
|
_num_channels = 4;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
pnmimage_cat.debug()
|
||||||
|
<< "Not a PFM file\n";
|
||||||
_is_valid = false;
|
_is_valid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pfm.store(_image);
|
(*_file) >> _x_size >> _y_size >> _scale;
|
||||||
PNMImageHeader::operator = (_image);
|
if (!(*_file)) {
|
||||||
|
pnmimage_cat.debug()
|
||||||
|
<< "Error parsing PFM header\n";
|
||||||
|
_is_valid = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip the last newline/whitespace character before the raw data
|
||||||
|
// begins.
|
||||||
|
(*_file).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PNMFileTypePfm::Reader::read_data
|
// Function: PNMFileTypePfm::Reader::is_floating_point
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
// Description: Reads in an entire image all at once, storing it in
|
// Description: Returns true if this PNMFileType represents a
|
||||||
// the pre-allocated _x_size * _y_size array and alpha
|
// floating-point image type, false if it is a normal,
|
||||||
// pointers. (If the image type has no alpha channel,
|
// integer type. If this returns true, read_pfm() is
|
||||||
// alpha is ignored.) Returns the number of rows
|
// implemented instead of read_data().
|
||||||
// correctly read.
|
|
||||||
//
|
|
||||||
// Derived classes need not override this if they
|
|
||||||
// instead provide supports_read_row() and read_row(),
|
|
||||||
// below.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
int PNMFileTypePfm::Reader::
|
bool PNMFileTypePfm::Reader::
|
||||||
read_data(xel *array, xelval *alpha) {
|
is_floating_point() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PNMFileTypePfm::Reader::read_pfm
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description: Reads floating-point data directly into the indicated
|
||||||
|
// PfmFile. Returns true on success, false on failure.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool PNMFileTypePfm::Reader::
|
||||||
|
read_pfm(PfmFile &pfm) {
|
||||||
if (!is_valid()) {
|
if (!is_valid()) {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
nassertr(_image.get_x_size() == get_x_size() &&
|
bool little_endian = false;
|
||||||
_image.get_y_size() == get_y_size(), 0);
|
if (_scale < 0) {
|
||||||
|
_scale = -_scale;
|
||||||
memcpy(array, _image.get_array(), get_x_size() * get_y_size() * sizeof(xel));
|
little_endian = true;
|
||||||
|
}
|
||||||
if (has_alpha()) {
|
if (pfm_force_littleendian) {
|
||||||
memcpy(alpha, _image.get_alpha_array(), get_x_size() * get_y_size() * sizeof(xelval));
|
little_endian = true;
|
||||||
|
}
|
||||||
|
if (pfm_reverse_dimensions) {
|
||||||
|
int t = _x_size;
|
||||||
|
_x_size = _y_size;
|
||||||
|
_y_size = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
return get_y_size();
|
pfm.clear(_x_size, _y_size, _num_channels);
|
||||||
|
pfm.set_scale(_scale);
|
||||||
|
|
||||||
|
// So far, so good. Now read the data.
|
||||||
|
int size = _x_size * _y_size * _num_channels;
|
||||||
|
|
||||||
|
pvector<PN_float32> table;
|
||||||
|
pfm.swap_table(table);
|
||||||
|
|
||||||
|
(*_file).read((char *)&table[0], sizeof(PN_float32) * size);
|
||||||
|
if ((*_file).fail() && !(*_file).eof()) {
|
||||||
|
pfm.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we may have to endian-reverse the data.
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
bool endian_reversed = little_endian;
|
||||||
|
#else
|
||||||
|
bool endian_reversed = !little_endian;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (endian_reversed) {
|
||||||
|
for (int ti = 0; ti < size; ++ti) {
|
||||||
|
ReversedNumericData nd(&table[ti], sizeof(PN_float32));
|
||||||
|
nd.store_value(&table[ti], sizeof(PN_float32));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pfm.swap_table(table);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -188,52 +259,79 @@ Writer(PNMFileType *type, ostream *file, bool owns_file) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PNMFileTypePfm::write_data
|
// Function: PNMFileTypePfm::Writer::supports_floating_point
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
// Description: Writes out an entire image all at once, including the
|
// Description: Returns true if this PNMFileType can accept a
|
||||||
// header, based on the image data stored in the given
|
// floating-point image type, false if it can only
|
||||||
// _x_size * _y_size array and alpha pointers. (If the
|
// accept a normal, integer type. If this returns true,
|
||||||
// image type has no alpha channel, alpha is ignored.)
|
// write_pfm() is implemented.
|
||||||
// Returns the number of rows correctly written.
|
|
||||||
//
|
|
||||||
// It is the user's responsibility to fill in the header
|
|
||||||
// data via calls to set_x_size(), set_num_channels(),
|
|
||||||
// etc., or copy_header_from(), before calling
|
|
||||||
// write_data().
|
|
||||||
//
|
|
||||||
// It is important to delete the PNMWriter class after
|
|
||||||
// successfully writing the data. Failing to do this
|
|
||||||
// may result in some data not getting flushed!
|
|
||||||
//
|
|
||||||
// Derived classes need not override this if they
|
|
||||||
// instead provide supports_streaming() and write_row(),
|
|
||||||
// below.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
int PNMFileTypePfm::Writer::
|
bool PNMFileTypePfm::Writer::
|
||||||
write_data(xel *array, xelval *alpha) {
|
supports_floating_point() {
|
||||||
if (_x_size <= 0 || _y_size <= 0) {
|
return true;
|
||||||
return 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
PNMImage image;
|
////////////////////////////////////////////////////////////////////
|
||||||
image.copy_header_from(*this);
|
// Function: PNMFileTypePfm::Writer::supports_integer
|
||||||
nassertr(image.get_x_size() == get_x_size() &&
|
// Access: Public, Virtual
|
||||||
image.get_y_size() == get_y_size(), 0);
|
// Description: Returns true if this PNMFileType can accept an
|
||||||
memcpy(image.get_array(), array, get_x_size() * get_y_size() * sizeof(xel));
|
// integer image type, false if it can only
|
||||||
if (has_alpha()) {
|
// accept a floating-point type. If this returns true,
|
||||||
memcpy(image.get_alpha_array(), alpha, get_x_size() * get_y_size() * sizeof(xelval));
|
// write_data() or write_row() is implemented.
|
||||||
}
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool PNMFileTypePfm::Writer::
|
||||||
|
supports_integer() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
PfmFile pfm;
|
////////////////////////////////////////////////////////////////////
|
||||||
if (!pfm.load(image)) {
|
// Function: PNMFileTypePfm::Writer::write_pfm
|
||||||
return 0;
|
// Access: Public, Virtual
|
||||||
}
|
// Description: Writes floating-point data from the indicated
|
||||||
|
// PfmFile. Returns true on success, false on failure.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool PNMFileTypePfm::Writer::
|
||||||
|
write_pfm(const PfmFile &pfm) {
|
||||||
|
nassertr(pfm.is_valid(), false);
|
||||||
|
|
||||||
if (!pfm.write(*_file)) {
|
switch (pfm.get_num_channels()) {
|
||||||
return 0;
|
case 1:
|
||||||
}
|
(*_file) << "Pf\n";
|
||||||
|
break;
|
||||||
|
|
||||||
return get_y_size();
|
case 3:
|
||||||
|
(*_file) << "PF\n";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
(*_file) << "pf4c\n";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
nassertr(false, false);
|
||||||
|
}
|
||||||
|
(*_file) << pfm.get_x_size() << " " << pfm.get_y_size() << "\n";
|
||||||
|
|
||||||
|
PN_float32 scale = cabs(pfm.get_scale());
|
||||||
|
if (scale == 0.0f) {
|
||||||
|
scale = 1.0f;
|
||||||
|
}
|
||||||
|
#ifndef WORDS_BIGENDIAN
|
||||||
|
// Little-endian computers must write a negative scale to indicate
|
||||||
|
// the little-endian nature of the output.
|
||||||
|
scale = -scale;
|
||||||
|
#endif
|
||||||
|
(*_file) << scale << "\n";
|
||||||
|
|
||||||
|
int size = pfm.get_x_size() * pfm.get_y_size() * pfm.get_num_channels();
|
||||||
|
const pvector<PN_float32> &table = pfm.get_table();
|
||||||
|
(*_file).write((const char *)&table[0], sizeof(PN_float32) * size);
|
||||||
|
|
||||||
|
if ((*_file).fail()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
nassertr(sizeof(PN_float32) == 4, false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
@ -49,17 +49,20 @@ public:
|
|||||||
public:
|
public:
|
||||||
Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number);
|
Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number);
|
||||||
|
|
||||||
virtual int read_data(xel *array, xelval *alpha);
|
virtual bool is_floating_point();
|
||||||
|
virtual bool read_pfm(PfmFile &pfm);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PNMImage _image;
|
PN_float32 _scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Writer : public PNMWriter {
|
class Writer : public PNMWriter {
|
||||||
public:
|
public:
|
||||||
Writer(PNMFileType *type, ostream *file, bool owns_file);
|
Writer(PNMFileType *type, ostream *file, bool owns_file);
|
||||||
|
|
||||||
virtual int write_data(xel *array, xelval *alpha);
|
virtual bool supports_floating_point();
|
||||||
|
virtual bool supports_integer();
|
||||||
|
virtual bool write_pfm(const PfmFile &pfm);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -46,6 +46,8 @@ PUBLISHED:
|
|||||||
TF_allow_1d = 0x0010, // If texture is Nx1, make a 1-d texture
|
TF_allow_1d = 0x0010, // If texture is Nx1, make a 1-d texture
|
||||||
TF_generate_mipmaps = 0x0020, // Consider generating mipmaps
|
TF_generate_mipmaps = 0x0020, // Consider generating mipmaps
|
||||||
TF_multiview = 0x0040, // Load a multiview texture in pages
|
TF_multiview = 0x0040, // Load a multiview texture in pages
|
||||||
|
TF_integer = 0x0080, // Load as an integer (RGB) texture
|
||||||
|
TF_float = 0x0100, // Load as a floating-point (depth) texture
|
||||||
};
|
};
|
||||||
|
|
||||||
LoaderOptions(int flags = LF_search | LF_report_errors);
|
LoaderOptions(int flags = LF_search | LF_report_errors);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user