mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
officially support 2-channel PfmFile; load pfm into RGB, not BGR for texture loads
This commit is contained in:
parent
3aaa57181d
commit
7e645bdca6
@ -5912,13 +5912,61 @@ convert_from_pfm(PTA_uchar &image, size_t page_size, int 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_channel(i, j, c);
|
||||
++p;
|
||||
switch (num_components) {
|
||||
case 1:
|
||||
{
|
||||
for (int j = y_size-1; j >= 0; j--) {
|
||||
for (int i = 0; i < x_size; i++) {
|
||||
p[0] = pfm.get_channel(i, j, 0);
|
||||
++p;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
for (int j = y_size-1; j >= 0; j--) {
|
||||
for (int i = 0; i < x_size; i++) {
|
||||
p[0] = pfm.get_channel(i, j, 0);
|
||||
p[1] = pfm.get_channel(i, j, 1);
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
{
|
||||
// RGB -> BGR
|
||||
for (int j = y_size-1; j >= 0; j--) {
|
||||
for (int i = 0; i < x_size; i++) {
|
||||
p[0] = pfm.get_channel(i, j, 2);
|
||||
p[1] = pfm.get_channel(i, j, 1);
|
||||
p[2] = pfm.get_channel(i, j, 0);
|
||||
p += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
{
|
||||
// RGBA -> BGRA
|
||||
for (int j = y_size-1; j >= 0; j--) {
|
||||
for (int i = 0; i < x_size; i++) {
|
||||
p[0] = pfm.get_channel(i, j, 2);
|
||||
p[1] = pfm.get_channel(i, j, 1);
|
||||
p[2] = pfm.get_channel(i, j, 0);
|
||||
p[3] = pfm.get_channel(i, j, 3);
|
||||
p += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
nassertv((unsigned char *)p == &image[idx] + page_size);
|
||||
@ -6003,13 +6051,53 @@ convert_to_pfm(PfmFile &pfm, int x_size, int y_size,
|
||||
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_channel(i, j, c, *p);
|
||||
switch (num_components) {
|
||||
case 1:
|
||||
for (int j = y_size-1; j >= 0; j--) {
|
||||
for (int i = 0; i < x_size; i++) {
|
||||
pfm.set_channel(i, j, 0, p[0]);
|
||||
++p;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
for (int j = y_size-1; j >= 0; j--) {
|
||||
for (int i = 0; i < x_size; i++) {
|
||||
pfm.set_channel(i, j, 0, p[0]);
|
||||
pfm.set_channel(i, j, 1, p[1]);
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// BGR -> RGB
|
||||
for (int j = y_size-1; j >= 0; j--) {
|
||||
for (int i = 0; i < x_size; i++) {
|
||||
pfm.set_channel(i, j, 2, p[0]);
|
||||
pfm.set_channel(i, j, 1, p[1]);
|
||||
pfm.set_channel(i, j, 0, p[2]);
|
||||
p += 3;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// BGRA -> RGBA
|
||||
for (int j = y_size-1; j >= 0; j--) {
|
||||
for (int i = 0; i < x_size; i++) {
|
||||
pfm.set_channel(i, j, 2, p[0]);
|
||||
pfm.set_channel(i, j, 1, p[1]);
|
||||
pfm.set_channel(i, j, 0, p[2]);
|
||||
pfm.set_channel(i, j, 3, p[3]);
|
||||
p += 4;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
nassertr(false, false);
|
||||
}
|
||||
|
||||
nassertr((unsigned char *)p == &image[idx] + page_size, false);
|
||||
|
@ -87,11 +87,16 @@ clear() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PfmFile::clear
|
||||
// Access: Published
|
||||
// Description: Resets to an empty table with a specific size.
|
||||
// Description: Resets to an empty table with a specific size. The
|
||||
// case of num_channels == 0 is allowed only in the case
|
||||
// that x_size and y_size are also == 0; and this makes
|
||||
// an empty (and invalid) PfmFile.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PfmFile::
|
||||
clear(int x_size, int y_size, int num_channels) {
|
||||
nassertv(x_size >= 0 && y_size >= 0);
|
||||
nassertv(num_channels > 0 && num_channels <= 4 || (x_size == 0 && y_size == 0 && num_channels == 0));
|
||||
|
||||
_x_size = x_size;
|
||||
_y_size = y_size;
|
||||
_scale = 1.0;
|
||||
@ -323,25 +328,7 @@ load(const PNMImage &pnmimage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the number of channels, ignoring alpha.
|
||||
int num_channels;
|
||||
switch (pnmimage.get_num_channels()) {
|
||||
case 4:
|
||||
num_channels = 4;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
num_channels = 3;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 1:
|
||||
num_channels = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
num_channels = 3;
|
||||
}
|
||||
int num_channels = pnmimage.get_num_channels();
|
||||
|
||||
clear(pnmimage.get_x_size(), pnmimage.get_y_size(), num_channels);
|
||||
switch (num_channels) {
|
||||
@ -355,6 +342,18 @@ load(const PNMImage &pnmimage) {
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
for (int yi = 0; yi < pnmimage.get_y_size(); ++yi) {
|
||||
for (int xi = 0; xi < pnmimage.get_x_size(); ++xi) {
|
||||
PN_float32 *point = &_table[(yi * _x_size + xi) * _num_channels];
|
||||
point[0] = pnmimage.get_gray(xi, yi);
|
||||
point[1] = pnmimage.get_alpha(xi, yi);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
{
|
||||
for (int yi = 0; yi < pnmimage.get_y_size(); ++yi) {
|
||||
@ -417,11 +416,23 @@ store(PNMImage &pnmimage) const {
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
for (int yi = 0; yi < get_y_size(); ++yi) {
|
||||
for (int xi = 0; xi < get_x_size(); ++xi) {
|
||||
const LPoint2f &point = get_point2(xi, yi);
|
||||
pnmimage.set_gray(xi, yi, point[0]);
|
||||
pnmimage.set_alpha(xi, yi, point[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
{
|
||||
for (int yi = 0; yi < get_y_size(); ++yi) {
|
||||
for (int xi = 0; xi < get_x_size(); ++xi) {
|
||||
const LPoint3f &point = get_point(xi, yi);
|
||||
const LPoint3f &point = get_point3(xi, yi);
|
||||
pnmimage.set_xel(xi, yi, point[0], point[1], point[2]);
|
||||
}
|
||||
}
|
||||
@ -1055,6 +1066,32 @@ quick_filter_from(const PfmFile &from) {
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
from_y0 = 0.0;
|
||||
for (int to_y = 0; to_y < _y_size; ++to_y) {
|
||||
from_y1 = (to_y + 1.0) * y_scale;
|
||||
from_y1 = min(from_y1, (PN_float32)orig_y_size);
|
||||
|
||||
from_x0 = 0.0;
|
||||
for (int to_x = 0; to_x < _x_size; ++to_x) {
|
||||
from_x1 = (to_x + 1.0) * x_scale;
|
||||
from_x1 = min(from_x1, (PN_float32)orig_x_size);
|
||||
|
||||
// Now the box from (from_x0, from_y0) - (from_x1, from_y1)
|
||||
// but not including (from_x1, from_y1) maps to the pixel (to_x, to_y).
|
||||
LPoint2f result;
|
||||
from.box_filter_region(result, from_x0, from_y0, from_x1, from_y1);
|
||||
new_data.push_back(result[0]);
|
||||
new_data.push_back(result[1]);
|
||||
|
||||
from_x0 = from_x1;
|
||||
}
|
||||
from_y0 = from_y1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
{
|
||||
from_y0 = 0.0;
|
||||
@ -1725,6 +1762,14 @@ compute_sample_point(LPoint3f &result,
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
LPoint2f result2;
|
||||
box_filter_region(result2, x - xr, y - yr, x + xr, y + yr);
|
||||
result.set(result2[0], result2[1], 0.0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
box_filter_region(result, x - xr, y - yr, x + xr, y + yr);
|
||||
break;
|
||||
@ -1860,6 +1905,51 @@ box_filter_region(PN_float32 &result,
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PfmFile::box_filter_region
|
||||
// Access: Private
|
||||
// Description: Averages all the points in the rectangle from x0
|
||||
// .. y0 to x1 .. y1 into result. The region may be
|
||||
// defined by floating-point boundaries; the result will
|
||||
// be weighted by the degree of coverage of each
|
||||
// included point.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PfmFile::
|
||||
box_filter_region(LPoint2f &result,
|
||||
PN_float32 x0, PN_float32 y0, PN_float32 x1, PN_float32 y1) const {
|
||||
result = LPoint2f::zero();
|
||||
PN_float32 coverage = 0.0;
|
||||
|
||||
if (x1 < x0 || y1 < y0) {
|
||||
return;
|
||||
}
|
||||
nassertv(y0 >= 0.0 && y1 >= 0.0);
|
||||
|
||||
int y = (int)y0;
|
||||
// Get the first (partial) row
|
||||
box_filter_line(result, coverage, x0, y, x1, (PN_float32)(y+1)-y0);
|
||||
|
||||
int y_last = (int)y1;
|
||||
if (y < y_last) {
|
||||
y++;
|
||||
while (y < y_last) {
|
||||
// Get each consecutive (complete) row
|
||||
box_filter_line(result, coverage, x0, y, x1, 1.0);
|
||||
y++;
|
||||
}
|
||||
|
||||
// Get the final (partial) row
|
||||
PN_float32 y_contrib = y1 - (PN_float32)y_last;
|
||||
if (y_contrib > 0.0001) {
|
||||
box_filter_line(result, coverage, x0, y, x1, y_contrib);
|
||||
}
|
||||
}
|
||||
|
||||
if (coverage != 0.0) {
|
||||
result /= coverage;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PfmFile::box_filter_region
|
||||
// Access: Private
|
||||
@ -1979,6 +2069,35 @@ box_filter_line(PN_float32 &result, PN_float32 &coverage,
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PfmFile::box_filter_line
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PfmFile::
|
||||
box_filter_line(LPoint2f &result, PN_float32 &coverage,
|
||||
PN_float32 x0, int y, PN_float32 x1, PN_float32 y_contrib) const {
|
||||
int x = (int)x0;
|
||||
// Get the first (partial) xel
|
||||
box_filter_point(result, coverage, x, y, (PN_float32)(x+1)-x0, y_contrib);
|
||||
|
||||
int x_last = (int)x1;
|
||||
if (x < x_last) {
|
||||
x++;
|
||||
while (x < x_last) {
|
||||
// Get each consecutive (complete) xel
|
||||
box_filter_point(result, coverage, x, y, 1.0, y_contrib);
|
||||
x++;
|
||||
}
|
||||
|
||||
// Get the final (partial) xel
|
||||
PN_float32 x_contrib = x1 - (PN_float32)x_last;
|
||||
if (x_contrib > 0.0001) {
|
||||
box_filter_point(result, coverage, x, y, x_contrib, y_contrib);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PfmFile::box_filter_line
|
||||
// Access: Private
|
||||
@ -2055,6 +2174,24 @@ box_filter_point(PN_float32 &result, PN_float32 &coverage,
|
||||
coverage += contrib;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PfmFile::box_filter_point
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PfmFile::
|
||||
box_filter_point(LPoint2f &result, PN_float32 &coverage,
|
||||
int x, int y, PN_float32 x_contrib, PN_float32 y_contrib) const {
|
||||
if (!has_point(x, y)) {
|
||||
return;
|
||||
}
|
||||
const LPoint2f &point = get_point2(x, y);
|
||||
|
||||
PN_float32 contrib = x_contrib * y_contrib;
|
||||
result += point * contrib;
|
||||
coverage += contrib;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PfmFile::box_filter_point
|
||||
// Access: Private
|
||||
@ -2066,7 +2203,7 @@ box_filter_point(LPoint3f &result, PN_float32 &coverage,
|
||||
if (!has_point(x, y)) {
|
||||
return;
|
||||
}
|
||||
const LPoint3f &point = get_point(x, y);
|
||||
const LPoint3f &point = get_point3(x, y);
|
||||
|
||||
PN_float32 contrib = x_contrib * y_contrib;
|
||||
result += point * contrib;
|
||||
|
@ -29,7 +29,7 @@ class PNMWriter;
|
||||
// Class : PfmFile
|
||||
// Description : Defines a pfm file, a 2-d table of floating-point
|
||||
// numbers, either 3-component or 1-component, or with a
|
||||
// special extension, 4-component.
|
||||
// special extension, 2- or 4-component.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA_PNMIMAGE PfmFile : public PNMImageHeader {
|
||||
PUBLISHED:
|
||||
@ -147,18 +147,24 @@ private:
|
||||
|
||||
void box_filter_region(PN_float32 &result,
|
||||
PN_float32 x0, PN_float32 y0, PN_float32 x1, PN_float32 y1) const;
|
||||
void box_filter_region(LPoint2f &result,
|
||||
PN_float32 x0, PN_float32 y0, PN_float32 x1, PN_float32 y1) const;
|
||||
void box_filter_region(LPoint3f &result,
|
||||
PN_float32 x0, PN_float32 y0, PN_float32 x1, PN_float32 y1) const;
|
||||
void box_filter_region(LPoint4f &result,
|
||||
PN_float32 x0, PN_float32 y0, PN_float32 x1, PN_float32 y1) const;
|
||||
void box_filter_line(PN_float32 &result, PN_float32 &coverage,
|
||||
PN_float32 x0, int y, PN_float32 x1, PN_float32 y_contrib) const;
|
||||
void box_filter_line(LPoint2f &result, PN_float32 &coverage,
|
||||
PN_float32 x0, int y, PN_float32 x1, PN_float32 y_contrib) const;
|
||||
void box_filter_line(LPoint3f &result, PN_float32 &coverage,
|
||||
PN_float32 x0, int y, PN_float32 x1, PN_float32 y_contrib) const;
|
||||
void box_filter_line(LPoint4f &result, PN_float32 &coverage,
|
||||
PN_float32 x0, int y, PN_float32 x1, PN_float32 y_contrib) const;
|
||||
void box_filter_point(PN_float32 &result, PN_float32 &coverage,
|
||||
int x, int y, PN_float32 x_contrib, PN_float32 y_contrib) const;
|
||||
void box_filter_point(LPoint2f &result, PN_float32 &coverage,
|
||||
int x, int y, PN_float32 x_contrib, PN_float32 y_contrib) const;
|
||||
void box_filter_point(LPoint3f &result, PN_float32 &coverage,
|
||||
int x, int y, PN_float32 x_contrib, PN_float32 y_contrib) const;
|
||||
void box_filter_point(LPoint4f &result, PN_float32 &coverage,
|
||||
|
@ -150,6 +150,10 @@ Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) :
|
||||
} else if (magic_number == "Pf") {
|
||||
_num_channels = 1;
|
||||
|
||||
} else if (magic_number == "pf2c") {
|
||||
// Special DRZ extension.
|
||||
_num_channels = 2;
|
||||
|
||||
} else if (magic_number == "pf4c") {
|
||||
// Special DRZ extension.
|
||||
_num_channels = 4;
|
||||
@ -299,6 +303,10 @@ write_pfm(const PfmFile &pfm) {
|
||||
(*_file) << "Pf\n";
|
||||
break;
|
||||
|
||||
case 2:
|
||||
(*_file) << "pf2c\n";
|
||||
break;
|
||||
|
||||
case 3:
|
||||
(*_file) << "PF\n";
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user