mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
PNMImage::gamma_correct()
This commit is contained in:
parent
425fa2608e
commit
003aa9e3dd
@ -145,6 +145,16 @@ cmod(float x, float y) {
|
|||||||
return x - cfloor(x / y) * y;
|
return x - cfloor(x / y) * y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: cpow
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE float
|
||||||
|
cpow(float x, float y) {
|
||||||
|
return powf(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: cfloor
|
// Function: cfloor
|
||||||
// Description:
|
// Description:
|
||||||
@ -317,6 +327,15 @@ cmod(double x, double y) {
|
|||||||
return x - cfloor(x / y) * y;
|
return x - cfloor(x / y) * y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: cpow
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE double
|
||||||
|
cpow(double x, double y) {
|
||||||
|
return pow(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: cnan
|
// Function: cnan
|
||||||
// Description:
|
// Description:
|
||||||
|
@ -43,6 +43,7 @@ INLINE float catan2(float y, float x);
|
|||||||
INLINE float casin(float v);
|
INLINE float casin(float v);
|
||||||
INLINE float cacos(float v);
|
INLINE float cacos(float v);
|
||||||
INLINE float cmod(float x, float y);
|
INLINE float cmod(float x, float y);
|
||||||
|
INLINE float cpow(float x, float y);
|
||||||
|
|
||||||
INLINE double cfloor(double f);
|
INLINE double cfloor(double f);
|
||||||
INLINE double cceil(double f);
|
INLINE double cceil(double f);
|
||||||
@ -58,6 +59,7 @@ INLINE double catan2(double y, double x);
|
|||||||
INLINE double casin(double v);
|
INLINE double casin(double v);
|
||||||
INLINE double cacos(double v);
|
INLINE double cacos(double v);
|
||||||
INLINE double cmod(double x, double y);
|
INLINE double cmod(double x, double y);
|
||||||
|
INLINE double cpow(double x, double y);
|
||||||
|
|
||||||
// Returns true if the number is nan, false if it's a genuine number
|
// Returns true if the number is nan, false if it's a genuine number
|
||||||
// or infinity.
|
// or infinity.
|
||||||
|
@ -834,6 +834,71 @@ gaussian_filter(double radius) {
|
|||||||
gaussian_filter_from(radius, *this);
|
gaussian_filter_from(radius, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PNMImage::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 PNMImage::
|
||||||
|
gamma_correct(double from_gamma, double to_gamma) {
|
||||||
|
apply_exponent(from_gamma / to_gamma);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PNMImage::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 PNMImage::
|
||||||
|
gamma_correct_alpha(double from_gamma, double to_gamma) {
|
||||||
|
apply_exponent(1.0, from_gamma / to_gamma);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PNMImage::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 PNMImage::
|
||||||
|
apply_exponent(double gray_exponent) {
|
||||||
|
apply_exponent(gray_exponent, gray_exponent, gray_exponent, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PNMImage::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 PNMImage::
|
||||||
|
apply_exponent(double gray_exponent, double alpha_exponent) {
|
||||||
|
apply_exponent(gray_exponent, gray_exponent, gray_exponent, alpha_exponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PNMImage::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 PNMImage::
|
||||||
|
apply_exponent(double red_exponent, double green_exponent, double blue_exponent) {
|
||||||
|
apply_exponent(red_exponent, green_exponent, blue_exponent, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PNMImage::allocate_array
|
// Function: PNMImage::allocate_array
|
||||||
|
@ -226,26 +226,6 @@ alpha_fill_val(xelval alpha) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: PNMImage::remix_channels
|
|
||||||
// Access: Published
|
|
||||||
// Description: Transforms every pixel using the operation
|
|
||||||
// (Ro,Go,Bo) = conv.xform_point(Ri,Gi,Bi);
|
|
||||||
// Input must be a color image.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void PNMImage::
|
|
||||||
remix_channels(const LMatrix4 &conv) {
|
|
||||||
int nchannels = get_num_channels();
|
|
||||||
nassertv((nchannels >= 3) && (nchannels <= 4));
|
|
||||||
for (int y = 0; y < get_y_size(); y++) {
|
|
||||||
for (int x = 0; x < get_x_size(); x++) {
|
|
||||||
LVector3 inv(get_red(x,y),get_green(x,y),get_blue(x,y));
|
|
||||||
LVector3 outv(conv.xform_point(inv));
|
|
||||||
set_xel(x,y,outv[0],outv[1],outv[2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PNMImage::read
|
// Function: PNMImage::read
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -1296,6 +1276,122 @@ perlin_noise_fill(StackedPerlinNoise2 &perlin) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PNMImage::remix_channels
|
||||||
|
// Access: Published
|
||||||
|
// Description: Transforms every pixel using the operation
|
||||||
|
// (Ro,Go,Bo) = conv.xform_point(Ri,Gi,Bi);
|
||||||
|
// Input must be a color image.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void PNMImage::
|
||||||
|
remix_channels(const LMatrix4 &conv) {
|
||||||
|
int nchannels = get_num_channels();
|
||||||
|
nassertv((nchannels >= 3) && (nchannels <= 4));
|
||||||
|
for (int y = 0; y < get_y_size(); y++) {
|
||||||
|
for (int x = 0; x < get_x_size(); x++) {
|
||||||
|
LVector3 inv(get_red(x,y), get_green(x,y), get_blue(x,y));
|
||||||
|
LVector3 outv(conv.xform_point(inv));
|
||||||
|
set_xel(x, y, outv[0], outv[1], outv[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PNMImage::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.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void PNMImage::
|
||||||
|
apply_exponent(double red_exponent, double green_exponent, double blue_exponent,
|
||||||
|
double alpha_exponent) {
|
||||||
|
int num_channels = _num_channels;
|
||||||
|
if (has_alpha() && alpha_exponent == 1.0) {
|
||||||
|
// If the alpha_exponent is 1, don't bother to apply it.
|
||||||
|
--num_channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
if (red_exponent == 1.0 && green_exponent == 1.0 && blue_exponent == 1.0) {
|
||||||
|
// If the RGB components are all 1, apply only to the alpha channel.
|
||||||
|
switch (num_channels) {
|
||||||
|
case 1:
|
||||||
|
case 3:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
case 4:
|
||||||
|
for (y = 0; y < _y_size; ++y) {
|
||||||
|
for (x = 0; x < _x_size; ++x) {
|
||||||
|
double alpha = get_alpha(x, y);
|
||||||
|
alpha = cpow(alpha, blue_exponent);
|
||||||
|
set_alpha(x, y, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Apply to the color and/or alpha channels.
|
||||||
|
|
||||||
|
switch (num_channels) {
|
||||||
|
case 1:
|
||||||
|
for (y = 0; y < _y_size; ++y) {
|
||||||
|
for (x = 0; x < _x_size; ++x) {
|
||||||
|
double gray = get_gray(x, y);
|
||||||
|
gray = cpow(gray, blue_exponent);
|
||||||
|
set_gray(x, y, gray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
for (y = 0; y < _y_size; ++y) {
|
||||||
|
for (x = 0; x < _x_size; ++x) {
|
||||||
|
double gray = get_gray(x, y);
|
||||||
|
gray = cpow(gray, blue_exponent);
|
||||||
|
set_gray(x, y, gray);
|
||||||
|
|
||||||
|
double alpha = get_alpha(x, y);
|
||||||
|
alpha = cpow(alpha, blue_exponent);
|
||||||
|
set_alpha(x, y, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
for (y = 0; y < _y_size; ++y) {
|
||||||
|
for (x = 0; x < _x_size; ++x) {
|
||||||
|
LRGBColord color = get_xel(x, y);
|
||||||
|
color[0] = cpow(color[0], red_exponent);
|
||||||
|
color[1] = cpow(color[1], green_exponent);
|
||||||
|
color[2] = cpow(color[2], blue_exponent);
|
||||||
|
set_xel(x, y, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
for (y = 0; y < _y_size; ++y) {
|
||||||
|
for (x = 0; x < _x_size; ++x) {
|
||||||
|
LColord color = get_xel_a(x, y);
|
||||||
|
color[0] = cpow(color[0], red_exponent);
|
||||||
|
color[1] = cpow(color[1], green_exponent);
|
||||||
|
color[2] = cpow(color[2], blue_exponent);
|
||||||
|
color[3] = cpow(color[3], alpha_exponent);
|
||||||
|
set_xel_a(x, y, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PNMImage::setup_rc
|
// Function: PNMImage::setup_rc
|
||||||
// Access: Private
|
// Access: Private
|
||||||
|
@ -81,8 +81,6 @@ PUBLISHED:
|
|||||||
INLINE void fill(double red, double green, double blue);
|
INLINE void fill(double red, double green, double blue);
|
||||||
INLINE void fill(double gray = 0.0);
|
INLINE void fill(double gray = 0.0);
|
||||||
|
|
||||||
void remix_channels(const LMatrix4 &conv);
|
|
||||||
|
|
||||||
void fill_val(xelval red, xelval green, xelval blue);
|
void fill_val(xelval red, xelval green, xelval blue);
|
||||||
INLINE void fill_val(xelval gray = 0);
|
INLINE void fill_val(xelval gray = 0);
|
||||||
|
|
||||||
@ -236,6 +234,14 @@ PUBLISHED:
|
|||||||
unsigned long seed = 0);
|
unsigned long seed = 0);
|
||||||
void perlin_noise_fill(StackedPerlinNoise2 &perlin);
|
void perlin_noise_fill(StackedPerlinNoise2 &perlin);
|
||||||
|
|
||||||
|
void remix_channels(const LMatrix4 &conv);
|
||||||
|
INLINE void gamma_correct(double from_gamma, double to_gamma);
|
||||||
|
INLINE void gamma_correct_alpha(double from_gamma, double to_gamma);
|
||||||
|
INLINE void apply_exponent(double gray_exponent);
|
||||||
|
INLINE void apply_exponent(double gray_exponent, double alpha_exponent);
|
||||||
|
INLINE void apply_exponent(double red_exponent, double green_exponent, double blue_exponent);
|
||||||
|
void apply_exponent(double red_exponent, double green_exponent, double blue_exponent, double alpha_exponent);
|
||||||
|
|
||||||
LRGBColord get_average_xel() const;
|
LRGBColord get_average_xel() const;
|
||||||
LColord get_average_xel_a() const;
|
LColord get_average_xel_a() const;
|
||||||
double get_average_gray() const;
|
double get_average_gray() const;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user