mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
add PfmFile::gamma_correct(), PfmFile::apply_mask(), PNMImage::copy_channel_bits()
This commit is contained in:
parent
38ac0401ce
commit
8876f0939e
@ -593,6 +593,71 @@ compute_planar_bounds(const LPoint2d ¢er, 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
|
||||
|
@ -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
|
||||
@ -2101,7 +2131,11 @@ divide_sub_image(const PfmFile ©, 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
|
||||
|
@ -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);
|
||||
|
@ -152,6 +152,57 @@ copy_channel(const PNMImage ©, 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 ©, 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();
|
||||
}
|
||||
|
@ -90,6 +90,7 @@ PUBLISHED:
|
||||
|
||||
void copy_from(const PNMImage ©);
|
||||
void copy_channel(const PNMImage ©, int src_channel, int dest_channel);
|
||||
void copy_channel_bits(const PNMImage ©, int src_channel, int dest_channel, xelval src_mask, int right_shift);
|
||||
void copy_header_from(const PNMImageHeader &header);
|
||||
void take_from(PNMImage &orig);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user