add PfmFile::gamma_correct(), PfmFile::apply_mask(), PNMImage::copy_channel_bits()

This commit is contained in:
David Rose 2015-04-25 07:23:54 -07:00
parent 38ac0401ce
commit 8876f0939e
6 changed files with 314 additions and 86 deletions

View File

@ -16,7 +16,7 @@
////////////////////////////////////////////////////////////////////
// Function: PfmFile::is_valid
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool PfmFile::
is_valid() const {
@ -155,7 +155,7 @@ set_point2(int x, int y, const LVecBase2f &point) {
case 4:
(*(LPoint4f *)&_table[(y * _x_size + x) * _num_channels]).set(point[0], point[1], 0.0, 0.0);
break;
}
}
}
////////////////////////////////////////////////////////////////////
@ -276,7 +276,7 @@ set_point3(int x, int y, const LVecBase3f &point) {
case 4:
(*(LPoint4f *)&_table[(y * _x_size + x) * _num_channels]).set(point[0], point[1], 0.0f, 0.0f);
break;
}
}
}
////////////////////////////////////////////////////////////////////
@ -350,7 +350,7 @@ set_point4(int x, int y, const LVecBase4f &point) {
case 4:
*(LPoint4f *)&_table[(y * _x_size + x) * _num_channels] = point;
break;
}
}
}
////////////////////////////////////////////////////////////////////
@ -593,6 +593,71 @@ compute_planar_bounds(const LPoint2d &center, PN_float32 point_dist, PN_float32
return compute_planar_bounds(LCAST(PN_float32, center), point_dist, sample_radius, points_only);
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::gamma_correct
// Access: Published
// Description: Assuming the image was constructed with a gamma curve
// of from_gamma in the RGB channels, converts it to an
// image with a gamma curve of to_gamma in the RGB
// channels. Does not affect the alpha channel.
////////////////////////////////////////////////////////////////////
INLINE void PfmFile::
gamma_correct(float from_gamma, float to_gamma) {
apply_exponent(from_gamma / to_gamma);
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::gamma_correct_alpha
// Access: Published
// Description: Assuming the image was constructed with a gamma curve
// of from_gamma in the alpha channel, converts it to an
// image with a gamma curve of to_gamma in the alpha
// channel. Does not affect the RGB channels.
////////////////////////////////////////////////////////////////////
INLINE void PfmFile::
gamma_correct_alpha(float from_gamma, float to_gamma) {
apply_exponent(1.0, from_gamma / to_gamma);
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::apply_exponent
// Access: Published
// Description: Adjusts each channel of the image by raising the
// corresponding component value to the indicated
// exponent, such that L' = L ^ exponent.
////////////////////////////////////////////////////////////////////
INLINE void PfmFile::
apply_exponent(float gray_exponent) {
apply_exponent(gray_exponent, gray_exponent, gray_exponent, 1.0);
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::apply_exponent
// Access: Published
// Description: Adjusts each channel of the image by raising the
// corresponding component value to the indicated
// exponent, such that L' = L ^ exponent.
////////////////////////////////////////////////////////////////////
INLINE void PfmFile::
apply_exponent(float gray_exponent, float alpha_exponent) {
apply_exponent(gray_exponent, gray_exponent, gray_exponent, alpha_exponent);
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::apply_exponent
// Access: Published
// Description: Adjusts each channel of the image by raising the
// corresponding component value to the indicated
// exponent, such that L' = L ^ exponent. For a
// grayscale image, the blue_exponent value is used for
// the grayscale value, and red_exponent and
// green_exponent are unused.
////////////////////////////////////////////////////////////////////
INLINE void PfmFile::
apply_exponent(float c0_exponent, float c1_exponent, float c2_exponent) {
apply_exponent(c0_exponent, c1_exponent, c2_exponent, 1.0);
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::get_table
// Access: Public

View File

@ -233,7 +233,7 @@ write(const Filename &fullpath) {
<< "Unable to open " << filename << "\n";
return false;
}
if (pnmimage_cat.is_debug()) {
pnmimage_cat.debug()
<< "Writing PFM file " << filename << "\n";
@ -514,7 +514,7 @@ fill(const LPoint4f &value) {
}
}
break;
}
}
}
////////////////////////////////////////////////////////////////////
@ -767,7 +767,7 @@ calc_min_max(LVecBase3f &min_depth, LVecBase3f &max_depth) const {
if (!has_point(xi, yi)) {
continue;
}
const LPoint3f &p = get_point(xi, yi);
if (!any_points) {
min_depth = p;
@ -783,7 +783,7 @@ calc_min_max(LVecBase3f &min_depth, LVecBase3f &max_depth) const {
}
}
}
return any_points;
}
@ -839,7 +839,7 @@ calc_autocrop(int &x_begin, int &x_end, int &y_begin, int &y_end) const {
////////////////////////////////////////////////////////////////////
bool PfmFile::
is_row_empty(int y, int x_begin, int x_end) const {
nassertr(y >= 0 && y < _y_size &&
nassertr(y >= 0 && y < _y_size &&
x_begin >= 0 && x_begin <= x_end && x_end <= _x_size, false);
if (!_has_no_data_value) {
@ -863,7 +863,7 @@ is_row_empty(int y, int x_begin, int x_end) const {
////////////////////////////////////////////////////////////////////
bool PfmFile::
is_column_empty(int x, int y_begin, int y_end) const {
nassertr(x >= 0 && x < _x_size &&
nassertr(x >= 0 && x < _x_size &&
y_begin >= 0 && y_begin <= y_end && y_end <= _y_size, false);
if (!_has_no_data_value) {
@ -1012,7 +1012,7 @@ resize(int new_x_size, int new_y_size) {
if (pfm_resize_quick && new_x_size <= _x_size && new_y_size <= _y_size) {
// If we're downscaling, we can use quick_filter, which is faster.
result.quick_filter_from(*this);
} else {
// Otherwise, we should use box_filter() or gaussian_filter, which
// are more general.
@ -1068,18 +1068,18 @@ quick_filter_from(const PfmFile &from) {
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).
PN_float32 result;
from.box_filter_region(result, from_x0, from_y0, from_x1, from_y1);
new_data.push_back(result);
from_x0 = from_x1;
}
from_y0 = from_y1;
@ -1093,19 +1093,19 @@ quick_filter_from(const PfmFile &from) {
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;
@ -1119,12 +1119,12 @@ quick_filter_from(const PfmFile &from) {
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).
LPoint3f result;
@ -1132,7 +1132,7 @@ quick_filter_from(const PfmFile &from) {
new_data.push_back(result[0]);
new_data.push_back(result[1]);
new_data.push_back(result[2]);
from_x0 = from_x1;
}
from_y0 = from_y1;
@ -1146,12 +1146,12 @@ quick_filter_from(const PfmFile &from) {
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).
LPoint4f result;
@ -1160,14 +1160,14 @@ quick_filter_from(const PfmFile &from) {
new_data.push_back(result[1]);
new_data.push_back(result[2]);
new_data.push_back(result[3]);
from_x0 = from_x1;
}
from_y0 = from_y1;
}
}
break;
default:
nassertv(false);
}
@ -1196,7 +1196,7 @@ reverse_rows() {
for (int yi = 0; yi < _y_size; ++yi) {
int source_yi = _y_size - 1 - yi;
int start = source_yi * row_size;
reversed.insert(reversed.end(),
reversed.insert(reversed.end(),
_table.begin() + start, _table.begin() + start + row_size);
}
@ -1290,7 +1290,7 @@ xform(const LMatrix4f &transform) {
// Description: Applies the distortion indicated in the supplied dist
// map to the current map. The dist map is understood
// to be a mapping of points in the range 0..1 in the
// first two dimensions.
// first two dimensions.
//
// The operation can be expressed symbolically as:
//
@ -1334,7 +1334,7 @@ forward_distort(const PfmFile &dist, PN_float32 scale_factor) {
PfmFile result;
result.clear(working_x_size, working_y_size, _num_channels);
if (_has_no_data_value) {
result.set_no_data_value(_no_data_value);
result.fill(_no_data_value);
@ -1412,7 +1412,7 @@ reverse_distort(const PfmFile &dist, PN_float32 scale_factor) {
PfmFile result;
result.clear(working_x_size, working_y_size, _num_channels);
if (_has_no_data_value) {
result.set_no_data_value(_no_data_value);
result.fill(_no_data_value);
@ -1466,6 +1466,36 @@ merge(const PfmFile &other) {
}
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::apply_mask
// Access: Published
// Description: Wherever there is missing data in the other PfmFile,
// set this the corresponding point in this PfmFile to
// missing as well, so that this PfmFile has only points
// where both files have points.
//
// The point is set to "missing" by setting it the
// no_data_value.
////////////////////////////////////////////////////////////////////
void PfmFile::
apply_mask(const PfmFile &other) {
nassertv(is_valid() && other.is_valid());
nassertv(other._x_size == _x_size && other._y_size == _y_size);
if (!other._has_no_data_value || !_has_no_data_value) {
// Trivial no-op.
return;
}
for (int yi = 0; yi < _y_size; ++yi) {
for (int xi = 0; xi < _x_size; ++xi) {
if (!other.has_point(xi, yi)) {
set_point4(xi, yi, _no_data_value);
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::copy_channel
// Access: Published
@ -1774,7 +1804,7 @@ compute_planar_bounds(const LPoint2f &center, PN_float32 point_dist, PN_float32
}
PT(BoundingHexahedron) bounds;
// We create a BoundingHexahedron with the points in a particular
// well-defined order, based on the current coordinate system.
CoordinateSystem cs = get_default_coordinate_system();
@ -1941,7 +1971,7 @@ copy_sub_image(const PfmFile &copy, int xto, int yto,
}
}
break;
}
}
}
////////////////////////////////////////////////////////////////////
@ -2008,7 +2038,7 @@ add_sub_image(const PfmFile &copy, int xto, int yto,
}
}
break;
}
}
}
////////////////////////////////////////////////////////////////////
@ -2101,7 +2131,11 @@ divide_sub_image(const PfmFile &copy, int xto, int yto,
for (y = ymin; y < ymax; y++) {
for (x = xmin; x < xmax; x++) {
if (has_point(x, y) && copy.has_point(x - xmin + xfrom, y - ymin + yfrom)) {
set_point1(x, y, get_point1(x, y) / copy.get_point1(x - xmin + xfrom, y - ymin + yfrom) * pixel_scale);
float val = get_point1(x, y) / copy.get_point1(x - xmin + xfrom, y - ymin + yfrom) * pixel_scale;
if (cnan(val)) {
val = 0.0f;
}
set_point1(x, y, val);
}
}
}
@ -2224,6 +2258,69 @@ operator *= (float multiplier) {
}
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::apply_exponent
// Access: Published
// Description: Adjusts each channel of the image by raising the
// corresponding component value to the indicated
// exponent, such that L' = L ^ exponent.
////////////////////////////////////////////////////////////////////
void PfmFile::
apply_exponent(float c0_exponent, float c1_exponent, float c2_exponent,
float c3_exponent) {
switch (_num_channels) {
case 1:
{
for (int yi = 0; yi < _y_size; ++yi) {
for (int xi = 0; xi < _x_size; ++xi) {
float *val = &_table[(yi * _x_size + xi)];
val[0] = cpow(val[0], c0_exponent);
}
}
}
break;
case 2:
{
for (int yi = 0; yi < _y_size; ++yi) {
for (int xi = 0; xi < _x_size; ++xi) {
float *val = &_table[(yi * _x_size + xi) * _num_channels];
val[0] = cpow(val[0], c0_exponent);
val[1] = cpow(val[1], c1_exponent);
}
}
}
break;
case 3:
{
for (int yi = 0; yi < _y_size; ++yi) {
for (int xi = 0; xi < _x_size; ++xi) {
float *val = &_table[(yi * _x_size + xi) * _num_channels];
val[0] = cpow(val[0], c0_exponent);
val[1] = cpow(val[1], c1_exponent);
val[2] = cpow(val[2], c2_exponent);
}
}
}
break;
case 4:
{
for (int yi = 0; yi < _y_size; ++yi) {
for (int xi = 0; xi < _x_size; ++xi) {
float *val = &_table[(yi * _x_size + xi) * _num_channels];
val[0] = cpow(val[0], c0_exponent);
val[1] = cpow(val[1], c1_exponent);
val[2] = cpow(val[2], c2_exponent);
val[3] = cpow(val[3], c3_exponent);
}
}
}
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::output
// Access: Published
@ -2418,7 +2515,7 @@ box_filter_region(LPoint4f &result,
////////////////////////////////////////////////////////////////////
// Function: PfmFile::box_filter_line
// Access: Private
// Description:
// Description:
////////////////////////////////////////////////////////////////////
void PfmFile::
box_filter_line(PN_float32 &result, PN_float32 &coverage,
@ -2447,7 +2544,7 @@ box_filter_line(PN_float32 &result, PN_float32 &coverage,
////////////////////////////////////////////////////////////////////
// Function: PfmFile::box_filter_line
// Access: Private
// Description:
// Description:
////////////////////////////////////////////////////////////////////
void PfmFile::
box_filter_line(LPoint2f &result, PN_float32 &coverage,
@ -2476,7 +2573,7 @@ box_filter_line(LPoint2f &result, PN_float32 &coverage,
////////////////////////////////////////////////////////////////////
// Function: PfmFile::box_filter_line
// Access: Private
// Description:
// Description:
////////////////////////////////////////////////////////////////////
void PfmFile::
box_filter_line(LPoint3f &result, PN_float32 &coverage,
@ -2505,7 +2602,7 @@ box_filter_line(LPoint3f &result, PN_float32 &coverage,
////////////////////////////////////////////////////////////////////
// Function: PfmFile::box_filter_line
// Access: Private
// Description:
// Description:
////////////////////////////////////////////////////////////////////
void PfmFile::
box_filter_line(LPoint4f &result, PN_float32 &coverage,
@ -2534,7 +2631,7 @@ box_filter_line(LPoint4f &result, PN_float32 &coverage,
////////////////////////////////////////////////////////////////////
// Function: PfmFile::box_filter_point
// Access: Private
// Description:
// Description:
////////////////////////////////////////////////////////////////////
void PfmFile::
box_filter_point(PN_float32 &result, PN_float32 &coverage,
@ -2552,7 +2649,7 @@ box_filter_point(PN_float32 &result, PN_float32 &coverage,
////////////////////////////////////////////////////////////////////
// Function: PfmFile::box_filter_point
// Access: Private
// Description:
// Description:
////////////////////////////////////////////////////////////////////
void PfmFile::
box_filter_point(LPoint2f &result, PN_float32 &coverage,
@ -2570,7 +2667,7 @@ box_filter_point(LPoint2f &result, PN_float32 &coverage,
////////////////////////////////////////////////////////////////////
// Function: PfmFile::box_filter_point
// Access: Private
// Description:
// Description:
////////////////////////////////////////////////////////////////////
void PfmFile::
box_filter_point(LPoint3f &result, PN_float32 &coverage,
@ -2588,7 +2685,7 @@ box_filter_point(LPoint3f &result, PN_float32 &coverage,
////////////////////////////////////////////////////////////////////
// Function: PfmFile::box_filter_point
// Access: Private
// Description:
// Description:
////////////////////////////////////////////////////////////////////
void PfmFile::
box_filter_point(LPoint4f &result, PN_float32 &coverage,
@ -2611,7 +2708,7 @@ box_filter_point(LPoint4f &result, PN_float32 &coverage,
// with the index to the nearest value.
////////////////////////////////////////////////////////////////////
void PfmFile::
fill_mini_grid(MiniGridCell *mini_grid, int x_size, int y_size,
fill_mini_grid(MiniGridCell *mini_grid, int x_size, int y_size,
int xi, int yi, int dist, int sxi, int syi) const {
if (xi < 0 || xi >= x_size || yi < 0 || yi >= y_size) {
// Out of bounds.
@ -2634,12 +2731,12 @@ fill_mini_grid(MiniGridCell *mini_grid, int x_size, int y_size,
////////////////////////////////////////////////////////////////////
// Function: PfmFile::has_point_noop
// Access: Private, Static
// Description: The implementation of has_point() for
// Description: The implementation of has_point() for
// files without a no_data_value.
////////////////////////////////////////////////////////////////////
bool PfmFile::
has_point_noop(const PfmFile *self, int x, int y) {
if ((x >= 0 && x < self->_x_size) &&
if ((x >= 0 && x < self->_x_size) &&
(y >= 0 && y < self->_y_size)) {
return true;
}
@ -2654,7 +2751,7 @@ has_point_noop(const PfmFile *self, int x, int y) {
////////////////////////////////////////////////////////////////////
bool PfmFile::
has_point_1(const PfmFile *self, int x, int y) {
if ((x >= 0 && x < self->_x_size) &&
if ((x >= 0 && x < self->_x_size) &&
(y >= 0 && y < self->_y_size)) {
return self->_table[(y * self->_x_size + x)] != self->_no_data_value[0];
}
@ -2669,7 +2766,7 @@ has_point_1(const PfmFile *self, int x, int y) {
////////////////////////////////////////////////////////////////////
bool PfmFile::
has_point_2(const PfmFile *self, int x, int y) {
if ((x >= 0 && x < self->_x_size) &&
if ((x >= 0 && x < self->_x_size) &&
(y >= 0 && y < self->_y_size)) {
return *(LPoint2f *)&self->_table[(y * self->_x_size + x) * 2] != *(LPoint2f *)&self->_no_data_value;
}
@ -2684,7 +2781,7 @@ has_point_2(const PfmFile *self, int x, int y) {
////////////////////////////////////////////////////////////////////
bool PfmFile::
has_point_3(const PfmFile *self, int x, int y) {
if ((x >= 0 && x < self->_x_size) &&
if ((x >= 0 && x < self->_x_size) &&
(y >= 0 && y < self->_y_size)) {
return *(LPoint3f *)&self->_table[(y * self->_x_size + x) * 3] != *(LPoint3f *)&self->_no_data_value;
}
@ -2699,7 +2796,7 @@ has_point_3(const PfmFile *self, int x, int y) {
////////////////////////////////////////////////////////////////////
bool PfmFile::
has_point_4(const PfmFile *self, int x, int y) {
if ((x >= 0 && x < self->_x_size) &&
if ((x >= 0 && x < self->_x_size) &&
(y >= 0 && y < self->_y_size)) {
return *(LPoint4f *)&self->_table[(y * self->_x_size + x) * 4] != *(LPoint4f *)&self->_no_data_value;
}
@ -2714,7 +2811,7 @@ has_point_4(const PfmFile *self, int x, int y) {
////////////////////////////////////////////////////////////////////
bool PfmFile::
has_point_threshold_1(const PfmFile *self, int x, int y) {
if ((x >= 0 && x < self->_x_size) &&
if ((x >= 0 && x < self->_x_size) &&
(y >= 0 && y < self->_y_size)) {
const float *table = &self->_table[(y * self->_x_size + x)];
return table[0] >= self->_no_data_value[0];
@ -2730,7 +2827,7 @@ has_point_threshold_1(const PfmFile *self, int x, int y) {
////////////////////////////////////////////////////////////////////
bool PfmFile::
has_point_threshold_2(const PfmFile *self, int x, int y) {
if ((x >= 0 && x < self->_x_size) &&
if ((x >= 0 && x < self->_x_size) &&
(y >= 0 && y < self->_y_size)) {
const float *table = &self->_table[(y * self->_x_size + x) * 2];
return (table[0] >= self->_no_data_value[0] ||
@ -2747,7 +2844,7 @@ has_point_threshold_2(const PfmFile *self, int x, int y) {
////////////////////////////////////////////////////////////////////
bool PfmFile::
has_point_threshold_3(const PfmFile *self, int x, int y) {
if ((x >= 0 && x < self->_x_size) &&
if ((x >= 0 && x < self->_x_size) &&
(y >= 0 && y < self->_y_size)) {
const float *table = &self->_table[(y * self->_x_size + x) * 3];
return (table[0] >= self->_no_data_value[0] ||
@ -2765,7 +2862,7 @@ has_point_threshold_3(const PfmFile *self, int x, int y) {
////////////////////////////////////////////////////////////////////
bool PfmFile::
has_point_threshold_4(const PfmFile *self, int x, int y) {
if ((x >= 0 && x < self->_x_size) &&
if ((x >= 0 && x < self->_x_size) &&
(y >= 0 && y < self->_y_size)) {
const float *table = &self->_table[(y * self->_x_size + x) * 4];
return (table[0] >= self->_no_data_value[0] ||
@ -2785,7 +2882,7 @@ has_point_threshold_4(const PfmFile *self, int x, int y) {
////////////////////////////////////////////////////////////////////
bool PfmFile::
has_point_chan4(const PfmFile *self, int x, int y) {
if ((x >= 0 && x < self->_x_size) &&
if ((x >= 0 && x < self->_x_size) &&
(y >= 0 && y < self->_y_size)) {
return self->_table[(y * self->_x_size + x) * 4 + 3] >= 0.0;
}
@ -2795,13 +2892,13 @@ has_point_chan4(const PfmFile *self, int x, int y) {
////////////////////////////////////////////////////////////////////
// Function: PfmFile::has_point_nan_1
// Access: Private, Static
// Description: The implementation of has_point() for
// Description: The implementation of has_point() for
// files with set_no_data_nan() in effect. This means
// that the data is valid iff no components involve NaN.
////////////////////////////////////////////////////////////////////
bool PfmFile::
has_point_nan_1(const PfmFile *self, int x, int y) {
if ((x >= 0 && x < self->_x_size) &&
if ((x >= 0 && x < self->_x_size) &&
(y >= 0 && y < self->_y_size)) {
return !cnan(self->_table[(y * self->_x_size + x) * self->_num_channels]);
}
@ -2811,13 +2908,13 @@ has_point_nan_1(const PfmFile *self, int x, int y) {
////////////////////////////////////////////////////////////////////
// Function: PfmFile::has_point_nan_2
// Access: Private, Static
// Description: The implementation of has_point() for
// Description: The implementation of has_point() for
// files with set_no_data_nan() in effect. This means
// that the data is valid iff no components involve NaN.
////////////////////////////////////////////////////////////////////
bool PfmFile::
has_point_nan_2(const PfmFile *self, int x, int y) {
if ((x >= 0 && x < self->_x_size) &&
if ((x >= 0 && x < self->_x_size) &&
(y >= 0 && y < self->_y_size)) {
return !((LVecBase2f *)&self->_table[(y * self->_x_size + x) * self->_num_channels])->is_nan();
}
@ -2827,13 +2924,13 @@ has_point_nan_2(const PfmFile *self, int x, int y) {
////////////////////////////////////////////////////////////////////
// Function: PfmFile::has_point_nan_3
// Access: Private, Static
// Description: The implementation of has_point() for
// Description: The implementation of has_point() for
// files with set_no_data_nan() in effect. This means
// that the data is valid iff no components involve NaN.
////////////////////////////////////////////////////////////////////
bool PfmFile::
has_point_nan_3(const PfmFile *self, int x, int y) {
if ((x >= 0 && x < self->_x_size) &&
if ((x >= 0 && x < self->_x_size) &&
(y >= 0 && y < self->_y_size)) {
return !((LVecBase3f *)&self->_table[(y * self->_x_size + x) * self->_num_channels])->is_nan();
}
@ -2843,13 +2940,13 @@ has_point_nan_3(const PfmFile *self, int x, int y) {
////////////////////////////////////////////////////////////////////
// Function: PfmFile::has_point_nan_4
// Access: Private, Static
// Description: The implementation of has_point() for
// Description: The implementation of has_point() for
// files with set_no_data_nan() in effect. This means
// that the data is valid iff no components involve NaN.
////////////////////////////////////////////////////////////////////
bool PfmFile::
has_point_nan_4(const PfmFile *self, int x, int y) {
if ((x >= 0 && x < self->_x_size) &&
if ((x >= 0 && x < self->_x_size) &&
(y >= 0 && y < self->_y_size)) {
return !((LVecBase4f *)&self->_table[(y * self->_x_size + x) * self->_num_channels])->is_nan();
}

View File

@ -123,6 +123,7 @@ PUBLISHED:
BLOCKING void forward_distort(const PfmFile &dist, PN_float32 scale_factor = 1.0);
BLOCKING void reverse_distort(const PfmFile &dist, PN_float32 scale_factor = 1.0);
BLOCKING void merge(const PfmFile &other);
BLOCKING void apply_mask(const PfmFile &other);
BLOCKING void copy_channel(int to_channel, const PfmFile &other, int from_channel);
BLOCKING void copy_channel_masked(int to_channel, const PfmFile &other, int from_channel);
BLOCKING void apply_crop(int x_begin, int x_end, int y_begin, int y_end);
@ -155,6 +156,13 @@ PUBLISHED:
void operator *= (float multiplier);
INLINE void gamma_correct(float from_gamma, float to_gamma);
INLINE void gamma_correct_alpha(float from_gamma, float to_gamma);
INLINE void apply_exponent(float gray_exponent);
INLINE void apply_exponent(float gray_exponent, float alpha_exponent);
INLINE void apply_exponent(float c0_exponent, float c1_exponent, float c2_exponent);
void apply_exponent(float c0_exponent, float c1_exponent, float c2_exponent, float c3_exponent);
void output(ostream &out) const;
EXTENSION(PyObject *get_points() const);
@ -204,7 +212,7 @@ private:
int _dist;
};
void fill_mini_grid(MiniGridCell *mini_grid, int x_size, int y_size,
void fill_mini_grid(MiniGridCell *mini_grid, int x_size, int y_size,
int xi, int yi, int dist, int sxi, int syi) const;
static bool has_point_noop(const PfmFile *file, int x, int y);

View File

@ -152,6 +152,57 @@ copy_channel(const PNMImage &copy, int src_channel, int dest_channel) {
}
}
////////////////////////////////////////////////////////////////////
// Function: PNMImage::copy_channel_bits
// Access: Published
// Description: Copies some subset of the bits of the specified
// channel from one image into some subset of the bits
// of the specified channel in another image. Images
// must be the same size.
//
// If right_shift is negative, it means a left shift.
////////////////////////////////////////////////////////////////////
void PNMImage::
copy_channel_bits(const PNMImage &copy, int src_channel, int dest_channel, xelval src_mask, int right_shift) {
// Make sure the channels are in range
nassertv(src_channel >= 0 && src_channel <= 3);
nassertv(dest_channel >= 0 && dest_channel <= 3);
// Make sure that images are valid
if (!copy.is_valid() || !is_valid()) {
pnmimage_cat.error() << "One of the images is invalid!\n";
return;
}
// Make sure the images are the same size
if (_x_size != copy.get_x_size() || _y_size != copy.get_y_size()){
pnmimage_cat.error() << "Image size doesn't match!\n";
return;
}
// Do the actual copying.
if (right_shift >= 0) {
xelval dest_mask = ~(src_mask >> right_shift);
for (int x = 0; x < _x_size; x++) {
for (int y = 0; y < _y_size; y++) {
xelval src = copy.get_channel_val(x, y, src_channel);
xelval dest = get_channel_val(x, y, dest_channel);
dest = (dest & dest_mask) | ((src & src_mask) >> right_shift);
set_channel_val(x, y, dest_channel, dest);
}
}
} else {
int left_shift = -right_shift;
xelval dest_mask = ~(src_mask << left_shift);
for (int x = 0; x < _x_size; x++) {
for (int y = 0; y < _y_size; y++) {
xelval src = copy.get_channel_val(x, y, src_channel);
xelval dest = get_channel_val(x, y, dest_channel);
dest = (dest & dest_mask) | ((src & src_mask) << left_shift);
set_channel_val(x, y, dest_channel, dest);
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: PNMImage::copy_header_from
// Access: Published
@ -165,6 +216,12 @@ copy_header_from(const PNMImageHeader &header) {
clear();
PNMImageHeader::operator = (header);
if (_maxval == 0) {
_inv_maxval = 0.0f;
} else {
_inv_maxval = 1.0f / (float)_maxval;
}
if (has_alpha()) {
allocate_alpha();
}
@ -1708,7 +1765,7 @@ rescale(float min_val, float max_val) {
for (int y = 0; y < get_y_size(); y++) {
for (int x = 0; x < get_x_size(); x++) {
LRGBColorf xel = get_xel(x, y);
set_xel(x, y,
set_xel(x, y,
(xel[0] - min_val) / scale,
(xel[1] - min_val) / scale,
(xel[2] - min_val) / scale);
@ -1899,7 +1956,7 @@ unfiltered_stretch_from(const PNMImage &copy) {
}
}
if (has_alpha() && copy.has_alpha()) {
if (has_alpha() && copy.has_alpha()) {
for (int yt = 0; yt < get_y_size(); yt++) {
int ys = yt * copy.get_y_size() / get_y_size();
for (int xt = 0; xt < get_x_size(); xt++) {

View File

@ -90,6 +90,7 @@ PUBLISHED:
void copy_from(const PNMImage &copy);
void copy_channel(const PNMImage &copy, int src_channel, int dest_channel);
void copy_channel_bits(const PNMImage &copy, int src_channel, int dest_channel, xelval src_mask, int right_shift);
void copy_header_from(const PNMImageHeader &header);
void take_from(PNMImage &orig);

View File

@ -255,7 +255,7 @@ set_type(PNMFileType *type) {
// Description: Records the indicated color in the histogram.
////////////////////////////////////////////////////////////////////
INLINE void PNMImageHeader::
record_color(PNMImageHeader::HistMap &hist,
record_color(PNMImageHeader::HistMap &hist,
const PNMImageHeader::PixelSpec &color) {
// First, try to add the color with a count of 0, in case it does
// not already exist in the table.
@ -270,7 +270,7 @@ record_color(PNMImageHeader::HistMap &hist,
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::Constructor
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE PNMImageHeader::PixelSpec::
PixelSpec(xelval gray_value) :
@ -284,7 +284,7 @@ PixelSpec(xelval gray_value) :
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::Constructor
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE PNMImageHeader::PixelSpec::
PixelSpec(xelval gray_value, xelval alpha) :
@ -298,7 +298,7 @@ PixelSpec(xelval gray_value, xelval alpha) :
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::Constructor
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE PNMImageHeader::PixelSpec::
PixelSpec(xelval red, xelval green, xelval blue) :
@ -312,7 +312,7 @@ PixelSpec(xelval red, xelval green, xelval blue) :
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::Constructor
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE PNMImageHeader::PixelSpec::
PixelSpec(xelval red, xelval green, xelval blue, xelval alpha) :
@ -326,7 +326,7 @@ PixelSpec(xelval red, xelval green, xelval blue, xelval alpha) :
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::Constructor
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE PNMImageHeader::PixelSpec::
PixelSpec(const xel &rgb) :
@ -340,7 +340,7 @@ PixelSpec(const xel &rgb) :
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::Constructor
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE PNMImageHeader::PixelSpec::
PixelSpec(const xel &rgb, xelval alpha) :
@ -354,7 +354,7 @@ PixelSpec(const xel &rgb, xelval alpha) :
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::Copy Constructor
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE PNMImageHeader::PixelSpec::
PixelSpec(const PixelSpec &copy) :
@ -368,7 +368,7 @@ PixelSpec(const PixelSpec &copy) :
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::Copy Assignment Operator
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE void PNMImageHeader::PixelSpec::
operator = (const PixelSpec &copy) {
@ -381,7 +381,7 @@ operator = (const PixelSpec &copy) {
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::operator <
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool PNMImageHeader::PixelSpec::
operator < (const PixelSpec &other) const {
@ -391,7 +391,7 @@ operator < (const PixelSpec &other) const {
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::operator ==
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool PNMImageHeader::PixelSpec::
operator == (const PixelSpec &other) const {
@ -401,7 +401,7 @@ operator == (const PixelSpec &other) const {
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::operator !=
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool PNMImageHeader::PixelSpec::
operator != (const PixelSpec &other) const {
@ -411,7 +411,7 @@ operator != (const PixelSpec &other) const {
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::compare_to
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE int PNMImageHeader::PixelSpec::
compare_to(const PixelSpec &other) const {
@ -433,7 +433,7 @@ compare_to(const PixelSpec &other) const {
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::get_red
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE xelval PNMImageHeader::PixelSpec::
get_red() const {
@ -443,7 +443,7 @@ get_red() const {
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::get_green
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE xelval PNMImageHeader::PixelSpec::
get_green() const {
@ -453,7 +453,7 @@ get_green() const {
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::get_blue
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE xelval PNMImageHeader::PixelSpec::
get_blue() const {
@ -463,7 +463,7 @@ get_blue() const {
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::get_alpha
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE xelval PNMImageHeader::PixelSpec::
get_alpha() const {
@ -473,7 +473,7 @@ get_alpha() const {
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::set_red
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE void PNMImageHeader::PixelSpec::
set_red(xelval red) {
@ -483,7 +483,7 @@ set_red(xelval red) {
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::set_green
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE void PNMImageHeader::PixelSpec::
set_green(xelval green) {
@ -493,7 +493,7 @@ set_green(xelval green) {
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::set_blue
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE void PNMImageHeader::PixelSpec::
set_blue(xelval blue) {
@ -503,7 +503,7 @@ set_blue(xelval blue) {
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpec::set_alpha
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE void PNMImageHeader::PixelSpec::
set_alpha(xelval alpha) {
@ -541,7 +541,7 @@ size() {
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::PixelSpecCount::Constructor
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE PNMImageHeader::PixelSpecCount::
PixelSpecCount(const PNMImageHeader::PixelSpec &pixel, int count) :
@ -565,7 +565,7 @@ operator < (const PNMImageHeader::PixelSpecCount &other) const {
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::Histogram::Constructor
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE PNMImageHeader::Histogram::
Histogram() {