29 PNMImage(
int x_size,
int y_size,
int num_channels, xelval maxval,
34 clear(x_size, y_size, num_channels, maxval, type, color_space);
53 INLINE
void PNMImage::
71 return (xelval)std::min(std::max(0, input_value), (
int)
get_maxval());
79 to_val(
const LRGBColorf &value)
const {
81 switch (_xel_encoding) {
83 case XE_generic_alpha:
85 LRGBColorf scaled = value *
get_maxval() + 0.5f;
93 case XE_generic_sRGB_alpha:
103 case XE_uchar_sRGB_alpha:
107 case XE_uchar_sRGB_sse2:
108 case XE_uchar_sRGB_alpha_sse2:
109 encode_sRGB_uchar_sse2(LColorf(value, 0.0f), col);
115 LRGBColorf scaled = value * 8192.f + 4096.5f;
116 col.r = std::min(std::max(0, (
int)scaled[0]), 65535);
117 col.g = std::min(std::max(0, (
int)scaled[1]), 65535);
118 col.b = std::min(std::max(0, (
int)scaled[2]), 65535);
130 to_val(
float input_value)
const {
131 switch (_xel_encoding) {
133 case XE_generic_alpha:
134 return (
int)(std::min(1.0f, std::max(0.0f, input_value)) *
get_maxval() + 0.5f);
136 case XE_generic_sRGB:
137 case XE_generic_sRGB_alpha:
142 case XE_uchar_sRGB_alpha:
145 case XE_uchar_sRGB_sse2:
146 case XE_uchar_sRGB_alpha_sse2:
147 return encode_sRGB_uchar_sse2(input_value);
151 return std::min(std::max(0, (
int)((8192 * input_value) + 4096.5f)), 65535);
172 switch (_xel_encoding) {
174 case XE_generic_alpha:
175 return LRGBColorf(col.r, col.g, col.b) * _inv_maxval;
177 case XE_generic_sRGB:
178 case XE_generic_sRGB_alpha:
185 case XE_uchar_sRGB_alpha:
186 case XE_uchar_sRGB_sse2:
187 case XE_uchar_sRGB_alpha_sse2:
195 return LRGBColorf((
int)col.r - 4096,
197 (
int)col.b - 4096) * (1.f / 8192.f);
200 return LRGBColorf(0);
209 from_val(xelval input_value)
const {
210 switch (_xel_encoding) {
212 case XE_generic_alpha:
213 return std::min((
float)input_value * _inv_maxval, 1.0f);
215 case XE_generic_sRGB:
216 case XE_generic_sRGB_alpha:
220 case XE_uchar_sRGB_alpha:
221 case XE_uchar_sRGB_sse2:
222 case XE_uchar_sRGB_alpha_sse2:
227 return (input_value - 4096) * (1.f / 8192.f);
239 return (
float)input_value * _inv_maxval;
246 fill(
float red,
float green,
float blue) {
256 fill(gray, gray, gray);
289 _read_x_size = x_size;
290 _read_y_size = y_size;
291 _has_read_size =
true;
299 _has_read_size =
false;
307 return _has_read_size;
316 return _has_read_size ? _read_x_size :
get_x_size();
325 return _has_read_size ? _read_y_size :
get_y_size();
343 return (_array !=
nullptr);
354 nassertv(num_channels >= 1 && num_channels <= 4);
399 nassertr(x >= 0 && x < _x_size && y >= 0 && y < _y_size, _array[0]);
409 nassertr(x >= 0 && x < _x_size && y >= 0 && y < _y_size, _array[0]);
420 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
430 set_xel_val(
int x,
int y, xelval r, xelval g, xelval b) {
431 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
432 PPM_ASSIGN(row(y)[x], r, g, b);
443 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
444 PPM_ASSIGN(row(y)[x], gray, gray, gray);
495 nassertr(_alpha !=
nullptr && x >= 0 && x < _x_size && y >= 0 && y < _y_size, 0);
496 return alpha_row(y)[x];
507 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
508 PPM_PUTR(row(y)[x], r);
519 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
520 PPM_PUTG(row(y)[x], g);
531 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
532 PPM_PUTB(row(y)[x], b);
546 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
547 PPM_PUTB(row(y)[x], gray);
560 nassertv(_alpha !=
nullptr && x >= 0 && x < _x_size && y >= 0 && y < _y_size);
570 nassertr(x >= 0 && x < _x_size && y >= 0 && y < _y_size, LRGBColorf::zero());
579 set_xel(
int x,
int y,
const LRGBColorf &value) {
580 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
581 row(y)[x] =
to_val(value);
589 set_xel(
int x,
int y,
float r,
float g,
float b) {
590 set_xel(x, y, LRGBColorf(r, g, b));
598 set_xel(
int x,
int y,
float gray) {
599 xelval val =
to_val(gray);
609 const xel &col = row(y)[x];
611 switch (_xel_encoding) {
613 return LColorf(col.r, col.g, col.b, 0.0f) * _inv_maxval;
615 case XE_generic_alpha:
616 return LColorf(col.r, col.g, col.b, alpha_row(y)[x]) * _inv_maxval;
618 case XE_generic_sRGB:
625 case XE_generic_sRGB_alpha:
630 alpha_row(y)[x] * _inv_maxval);
633 case XE_uchar_sRGB_sse2:
640 case XE_uchar_sRGB_alpha:
641 case XE_uchar_sRGB_alpha_sse2:
646 alpha_row(y)[x] * (1.f / 255.f));
649 return LColorf((
int)col.r - 4096,
656 static const LColorf scale(1.f / 8192.f, 1.f / 8192.f, 1.f / 8192.f, 1.f / 65535.f);
657 LColorf color((
int)col.r - 4096,
661 color.componentwise_mult(scale);
675 set_xel_a(
int x,
int y,
const LColorf &value) {
676 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
678 xel &col = row(y)[x];
680 switch (_xel_encoding) {
690 case XE_generic_alpha:
696 alpha_row(y)[x] =
clamp_val((
int)scaled[3]);
700 case XE_generic_sRGB:
709 case XE_generic_sRGB_alpha:
723 case XE_uchar_sRGB_alpha:
727 case XE_uchar_sRGB_sse2:
728 encode_sRGB_uchar_sse2(value, col);
731 case XE_uchar_sRGB_alpha_sse2:
732 encode_sRGB_uchar_sse2(value, col, alpha_row(y)[x]);
737 LColorf scaled = value * 8192.0f + 4096.5f;
738 col.r = std::min(std::max(0, (
int)scaled[0]), 65535);
739 col.g = std::min(std::max(0, (
int)scaled[1]), 65535);
740 col.b = std::min(std::max(0, (
int)scaled[2]), 65535);
746 LColorf scaled = value * 8192.0f + 4096.5f;
747 col.r = std::min(std::max(0, (
int)scaled[0]), 65535);
748 col.g = std::min(std::max(0, (
int)scaled[1]), 65535);
749 col.b = std::min(std::max(0, (
int)scaled[2]), 65535);
750 alpha_row(y)[x] = std::min(std::max(0, (
int)(value[3] * 65535 + 0.5f)), 65535);
761 set_xel_a(
int x,
int y,
float r,
float g,
float b,
float a) {
818 set_red(
int x,
int y,
float r) {
849 set_gray(
int x,
int y,
float gray) {
870 return get_bright(x, y, _default_rc, _default_gc, _default_bc);
879 get_bright(
int x,
int y,
float rc,
float gc,
float bc)
const {
880 return get_xel(x, y).dot(LVecBase3f(rc, gc, bc));
889 get_bright(
int x,
int y,
float rc,
float gc,
float bc,
float ac)
const {
890 return get_xel_a(x, y).dot(LVecBase4f(rc, gc, bc, ac));
900 blend(
int x,
int y,
const LRGBColorf &val,
float alpha) {
901 blend(x, y, val[0], val[1], val[2], alpha);
957 apply_exponent(gray_exponent, gray_exponent, gray_exponent, alpha_exponent);
967 apply_exponent(
float red_exponent,
float green_exponent,
float blue_exponent) {
974 INLINE PNMImage::Row::
975 Row(
PNMImage &image,
int y) : _image(image), _y(y) {
976 nassertv(y >= 0 && y < _image._y_size);
992 return _image.get_xel_a(x, _y);
1000 INLINE
void PNMImage::Row::
1001 __setitem__(
int x,
const LColorf &v) {
1002 _image.set_xel_a(x, _y, v);
1011 return _image.get_xel_val(x, _y);
1019 _image.set_xel_val(x, _y, v);
1027 return _image.get_alpha_val(x, _y);
1035 _image.set_alpha_val(x, _y, v);
1041 INLINE PNMImage::CRow::
1042 CRow(
const PNMImage &image,
int y) : _image(image), _y(y) {
1043 nassertv(y >= 0 && y < _image._y_size);
1051 return _image.get_x_size();
1059 return _image.get_xel_a(x, _y);
1067 return _image.get_xel_val(x, _y);
1075 return _image.get_alpha_val(x, _y);
1083 return Row(*
this, y);
1091 return CRow(*
this, y);
1136 xel *array = _array;
1149 xelval *alpha = _alpha;
1158 INLINE
void PNMImage::
1160 _array = (
xel *)PANDA_MALLOC_ARRAY((
size_t)_x_size * (size_t)_y_size *
sizeof(
xel));
1166 INLINE
void PNMImage::
1168 _alpha = (xelval *)PANDA_MALLOC_ARRAY((
size_t)_x_size * (size_t)_y_size *
sizeof(xelval));
1174 INLINE
xel *PNMImage::
1176 nassertr(y >= 0 && y < _y_size,
nullptr);
1177 return _array + y * _x_size;
1184 INLINE xelval *PNMImage::
1185 alpha_row(
int y)
const {
1186 nassertr(_alpha !=
nullptr && y >= 0 && y < _y_size,
nullptr);
1187 return _alpha + y * _x_size;
1194 INLINE
void PNMImage::
1195 setup_sub_image(
const PNMImage ©,
int &xto,
int &yto,
1196 int &xfrom,
int &yfrom,
int &x_size,
int &y_size,
1197 int &xmin,
int &ymin,
int &xmax,
int &ymax) {
1227 x_size = std::min(x_size, copy.
get_x_size() - xfrom);
1228 y_size = std::min(y_size, copy.
get_y_size() - yfrom);
1233 xmax = std::min(xmin + x_size,
get_x_size());
1234 ymax = std::min(ymin + y_size,
get_y_size());
1241 INLINE
void PNMImage::
1242 compute_spot_pixel(LColorf &c,
float d2,
1243 float min_radius,
float max_radius,
1244 const LColorf &fg,
const LColorf &bg) {
1246 if (d > max_radius) {
1248 }
else if (d > min_radius) {
1249 d = (d - min_radius) / (max_radius - min_radius);
1251 float t = (3.0f * d2) - (2.0f * d * d2);
1252 c = fg + t * (bg - fg);
1324 target *= multiplier;
This is the base class of a family of classes that represent particular image file types that PNMImag...
size_t size() const
Get the number of pixels in the row.
xel get_xel_val(int x) const
Fetch the pixel at the given column in the row.
LColorf operator[](int x) const
Fetch the RGB value at the given column in the row.
xelval get_alpha_val(int x) const
Fetch the alpha value at the given column in the row.
void set_alpha_val(int x, xelval v)
Set the alpha value at the given column in the row.
xel & get_xel_val(int x)
Fetch the pixel at the given column in the row.
size_t size() const
Get the number of pixels in the row.
void set_xel_val(int x, const xel &v)
Set the pixel at the given column in the row.
xelval get_alpha_val(int x) const
Fetch the alpha value at the given column in the row.
LColorf operator[](int x) const
Fetch the RGB value at the given column in the row.
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
void clear()
Frees all memory allocated for the image, and clears all its parameters (size, color,...
xel & get_xel_val(int x, int y)
Returns the RGB color at the indicated pixel.
void set_xel_val(int x, int y, const xel &value)
Changes the RGB color at the indicated pixel.
void set_read_size(int x_size, int y_size)
Specifies the size to we'd like to scale the image upon reading it.
void set_blue(int x, int y, float b)
Sets the blue component color only at the indicated pixel.
void set_blue_val(int x, int y, xelval b)
Sets the blue component color only at the indicated pixel.
void fill_val(xelval red, xelval green, xelval blue)
Sets the entire image (except the alpha channel) to the given color.
void alpha_fill(float alpha=0.0)
Sets the entire alpha channel to the given level.
void gaussian_filter_from(float radius, const PNMImage ©)
Makes a resized copy of the indicated image into this one using the indicated filter.
void set_alpha_val(int x, int y, xelval a)
Sets the alpha component color only at the indicated pixel.
xelval get_green_val(int x, int y) const
Returns the green component color at the indicated pixel.
void make_grayscale()
Converts the image from RGB to grayscale.
PNMImage operator-(const PNMImage &other) const
Returns a new PNMImage in which each pixel value from the right image is subtracted from each pixel v...
void set_green(int x, int y, float g)
Sets the green component color only at the indicated pixel.
xel * take_array()
Returns the underlying PNMImage array and removes it from the PNMImage.
float get_blue(int x, int y) const
Returns the blue component color at the indicated pixel.
float get_alpha(int x, int y) const
Returns the alpha component color at the indicated pixel.
LRGBColorf get_xel(int x, int y) const
Returns the RGB color at the indicated pixel.
void set_xel_a(int x, int y, const LColorf &value)
Changes the RGBA color at the indicated pixel.
LRGBColorf from_val(const xel &input_value) const
A handy function to scale non-alpha values from [0..get_maxval()] to [0..1].
float get_gray(int x, int y) const
Returns the gray component color at the indicated pixel.
void remove_alpha()
Removes the image's alpha channel, if it exists.
xelval clamp_val(int input_value) const
A handy function to clamp values to [0..get_maxval()].
void fill(float red, float green, float blue)
Sets the entire image (except the alpha channel) to the given color.
void blend(int x, int y, const LRGBColorf &val, float alpha)
Smoothly blends the indicated pixel value in with whatever was already in the image,...
LColorf get_xel_a(int x, int y) const
Returns the RGBA color at the indicated pixel.
void set_num_channels(int num_channels)
Changes the number of channels associated with the image.
void make_rgb()
Converts the image from grayscale to RGB.
void set_gray(int x, int y, float gray)
Sets the gray component color at the indicated pixel.
xelval to_alpha_val(float input_value) const
A handy function to scale alpha values from [0..1] to [0..get_maxval()].
void set_color_type(ColorType color_type)
Translates the image to or from grayscale, color, or four-color mode.
void set_gray_val(int x, int y, xelval gray)
Sets the gray component color at the indicated pixel.
xelval get_alpha_val(int x, int y) const
Returns the alpha component color at the indicated pixel.
void set_red(int x, int y, float r)
Sets the red component color only at the indicated pixel.
void box_filter(float radius=1.0)
This flavor of box_filter() will apply the filter over the entire image without resizing or copying; ...
float get_bright(int x, int y) const
Returns the linear brightness of the given xel, as a linearized float in the range 0....
PNMImage operator*(const PNMImage &other) const
Returns a new PNMImage in which each pixel value from the left image is multiplied by each pixel valu...
bool has_read_size() const
Returns true if set_read_size() has been called.
void set_green_val(int x, int y, xelval g)
Sets the green component color only at the indicated pixel.
bool is_valid() const
Returns true if the image has been read in or correctly initialized with a height and width.
void copy_from(const PNMImage ©)
Makes this image become a copy of the other image.
float from_alpha_val(xelval input_value) const
A handy function to scale alpha values from [0..get_maxval()] to [0..1].
xelval get_blue_val(int x, int y) const
Returns the blue component color at the indicated pixel.
float get_green(int x, int y) const
Returns the green component color at the indicated pixel.
void gaussian_filter(float radius=1.0)
This flavor of gaussian_filter() will apply the filter over the entire image without resizing or copy...
xel * get_array()
Directly access the underlying PNMImage array.
xelval get_red_val(int x, int y) const
Returns the red component color at the indicated pixel.
void set_xel(int x, int y, const LRGBColorf &value)
Changes the RGB color at the indicated pixel.
void set_red_val(int x, int y, xelval r)
Sets the red component color only at the indicated pixel.
int get_read_y_size() const
Returns the requested y_size of the image if set_read_size() has been called, or the image y_size oth...
void box_filter_from(float radius, const PNMImage ©)
Makes a resized copy of the indicated image into this one using the indicated filter.
void gamma_correct(float from_gamma, float to_gamma)
Assuming the image was constructed with a gamma curve of from_gamma in the RGB channels,...
xelval * take_alpha_array()
Returns the underlying PNMImage array and removes it from the PNMImage.
xel to_val(const LRGBColorf &input_value) const
A handy function to scale non-alpha values from [0..1] to [0..get_maxval()].
void gamma_correct_alpha(float from_gamma, float to_gamma)
Assuming the image was constructed with a gamma curve of from_gamma in the alpha channel,...
xelval get_gray_val(int x, int y) const
Returns the gray component color at the indicated pixel.
void set_alpha(int x, int y, float a)
Sets the alpha component color only at the indicated pixel.
ColorSpace get_color_space() const
Returns the color space in which the image is encoded.
void apply_exponent(float gray_exponent)
Adjusts each channel of the image by raising the corresponding component value to the indicated expon...
void clear_read_size()
Undoes the effect of a previous call to set_read_size().
void add_alpha()
Adds an alpha channel to the image, if it does not already have one.
xelval * get_alpha_array()
Directly access the underlying PNMImage array of alpha values.
void alpha_fill_val(xelval alpha=0)
Sets the entire alpha channel to the given level.
Row operator[](int y)
Allows the PNMImage to appear to be a 2-d array of xels.
PNMImage operator+(const PNMImage &other) const
Returns a new PNMImage in which each pixel value is the sum of the corresponding pixel values in the ...
int get_read_x_size() const
Returns the requested x_size of the image if set_read_size() has been called, or the image x_size oth...
float get_red(int x, int y) const
Returns the red component color at the indicated pixel.
BEGIN_PUBLISH EXPCL_PANDA_PNMIMAGE float decode_sRGB_float(unsigned char val)
Decodes the sRGB-encoded unsigned char value to a linearized float in the range 0-1.
EXPCL_PANDA_PNMIMAGE float encode_sRGB_float(unsigned char val)
Encodes the linearized unsigned char value to an sRGB-encoded floating- point value in ther range 0-1...
EXPCL_PANDA_PNMIMAGE unsigned char encode_sRGB_uchar(unsigned char val)
Encodes the linearized unsigned char value to an sRGB-encoded unsigned char value.