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());
80 switch (_xel_encoding) {
82 case XE_generic_alpha:
83 return (
int)(std::min(1.0f, std::max(0.0f, input_value)) *
get_maxval() + 0.5f);
86 case XE_generic_sRGB_alpha:
91 case XE_uchar_sRGB_alpha:
94 case XE_uchar_sRGB_sse2:
95 case XE_uchar_sRGB_alpha_sse2:
96 return encode_sRGB_uchar_sse2(input_value);
100 return std::min(std::max(0, (
int)((8192 * input_value) + 4096.5f)), 65535);
121 switch (_xel_encoding) {
123 case XE_generic_alpha:
124 return (
float)input_value * _inv_maxval;
126 case XE_generic_sRGB:
127 case XE_generic_sRGB_alpha:
131 case XE_uchar_sRGB_alpha:
132 case XE_uchar_sRGB_sse2:
133 case XE_uchar_sRGB_alpha_sse2:
138 return (input_value - 4096) * (1.f / 8192.f);
150 return (
float)input_value * _inv_maxval;
157 fill(
float red,
float green,
float blue) {
167 fill(gray, gray, gray);
200 _read_x_size = x_size;
201 _read_y_size = y_size;
202 _has_read_size =
true;
210 _has_read_size =
false;
218 return _has_read_size;
227 return _has_read_size ? _read_x_size :
get_x_size();
236 return _has_read_size ? _read_y_size :
get_y_size();
254 return (_array !=
nullptr);
265 nassertv(num_channels >= 1 && num_channels <= 4);
310 nassertr(x >= 0 && x < _x_size && y >= 0 && y < _y_size, _array[0]);
320 nassertr(x >= 0 && x < _x_size && y >= 0 && y < _y_size, _array[0]);
331 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
342 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
343 PPM_ASSIGN(row(y)[x], r, g, b);
354 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
355 PPM_ASSIGN(row(y)[x], gray, gray, gray);
406 nassertr(_alpha !=
nullptr && x >= 0 && x < _x_size && y >= 0 && y < _y_size, 0);
407 return alpha_row(y)[x];
418 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
419 PPM_PUTR(row(y)[x], r);
430 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
431 PPM_PUTG(row(y)[x], g);
442 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
443 PPM_PUTB(row(y)[x], b);
457 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
458 PPM_PUTB(row(y)[x], gray);
471 nassertv(_alpha !=
nullptr && x >= 0 && x < _x_size && y >= 0 && y < _y_size);
481 nassertr(x >= 0 && x < _x_size && y >= 0 && y < _y_size, LRGBColorf::zero());
483 const xel &col = row(y)[x];
485 switch (_xel_encoding) {
487 case XE_generic_alpha:
488 return LRGBColorf(col.r, col.g, col.b) * _inv_maxval;
490 case XE_generic_sRGB:
491 case XE_generic_sRGB_alpha:
498 case XE_uchar_sRGB_alpha:
499 case XE_uchar_sRGB_sse2:
500 case XE_uchar_sRGB_alpha_sse2:
508 return LRGBColorf((
int)col.r - 4096,
510 (
int)col.b - 4096) * (1.f / 8192.f);
513 return LRGBColorf(0);
522 set_xel(
int x,
int y,
const LRGBColorf &value) {
523 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
525 xel &col = row(y)[x];
527 switch (_xel_encoding) {
529 case XE_generic_alpha:
531 LRGBColorf scaled = value *
get_maxval() + 0.5f;
538 case XE_generic_sRGB:
539 case XE_generic_sRGB_alpha:
549 case XE_uchar_sRGB_alpha:
553 case XE_uchar_sRGB_sse2:
554 case XE_uchar_sRGB_alpha_sse2:
555 encode_sRGB_uchar_sse2(LColorf(value, 0.0f), col);
561 LRGBColorf scaled = value * 8192.f + 4096.5f;
562 col.r = std::min(std::max(0, (
int)scaled[0]), 65535);
563 col.g = std::min(std::max(0, (
int)scaled[1]), 65535);
564 col.b = std::min(std::max(0, (
int)scaled[2]), 65535);
575 set_xel(
int x,
int y,
float r,
float g,
float b) {
576 set_xel(x, y, LRGBColorf(r, g, b));
585 xelval val =
to_val(gray);
595 const xel &col = row(y)[x];
597 switch (_xel_encoding) {
599 return LColorf(col.r, col.g, col.b, 0.0f) * _inv_maxval;
601 case XE_generic_alpha:
602 return LColorf(col.r, col.g, col.b, alpha_row(y)[x]) * _inv_maxval;
604 case XE_generic_sRGB:
611 case XE_generic_sRGB_alpha:
616 alpha_row(y)[x] * _inv_maxval);
619 case XE_uchar_sRGB_sse2:
626 case XE_uchar_sRGB_alpha:
627 case XE_uchar_sRGB_alpha_sse2:
632 alpha_row(y)[x] * (1.f / 255.f));
635 return LColorf((
int)col.r - 4096,
642 static const LColorf scale(1.f / 8192.f, 1.f / 8192.f, 1.f / 8192.f, 1.f / 65535.f);
643 LColorf color((
int)col.r - 4096,
647 color.componentwise_mult(scale);
662 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
664 xel &col = row(y)[x];
666 switch (_xel_encoding) {
676 case XE_generic_alpha:
682 alpha_row(y)[x] =
clamp_val((
int)scaled[3]);
686 case XE_generic_sRGB:
695 case XE_generic_sRGB_alpha:
709 case XE_uchar_sRGB_alpha:
713 case XE_uchar_sRGB_sse2:
714 encode_sRGB_uchar_sse2(value, col);
717 case XE_uchar_sRGB_alpha_sse2:
718 encode_sRGB_uchar_sse2(value, col, alpha_row(y)[x]);
723 LColorf scaled = value * 8192.0f + 4096.5f;
724 col.r = std::min(std::max(0, (
int)scaled[0]), 65535);
725 col.g = std::min(std::max(0, (
int)scaled[1]), 65535);
726 col.b = std::min(std::max(0, (
int)scaled[2]), 65535);
732 LColorf scaled = value * 8192.0f + 4096.5f;
733 col.r = std::min(std::max(0, (
int)scaled[0]), 65535);
734 col.g = std::min(std::max(0, (
int)scaled[1]), 65535);
735 col.b = std::min(std::max(0, (
int)scaled[2]), 65535);
736 alpha_row(y)[x] = std::min(std::max(0, (
int)(value[3] * 65535 + 0.5f)), 65535);
747 set_xel_a(
int x,
int y,
float r,
float g,
float b,
float a) {
856 return get_bright(x, y, _default_rc, _default_gc, _default_bc);
865 get_bright(
int x,
int y,
float rc,
float gc,
float bc)
const {
866 return get_xel(x, y).dot(LVecBase3f(rc, gc, bc));
875 get_bright(
int x,
int y,
float rc,
float gc,
float bc,
float ac)
const {
876 return get_xel_a(x, y).dot(LVecBase4f(rc, gc, bc, ac));
886 blend(
int x,
int y,
const LRGBColorf &val,
float alpha) {
887 blend(x, y, val[0], val[1], val[2], alpha);
943 apply_exponent(gray_exponent, gray_exponent, gray_exponent, alpha_exponent);
960 INLINE PNMImage::Row::
961 Row(
PNMImage &image,
int y) : _image(image), _y(y) {
962 nassertv(y >= 0 && y < _image._y_size);
978 return _image.get_xel_a(x, _y);
986 INLINE
void PNMImage::Row::
987 __setitem__(
int x,
const LColorf &v) {
988 _image.set_xel_a(x, _y, v);
997 return _image.get_xel_val(x, _y);
1005 _image.set_xel_val(x, _y, v);
1013 return _image.get_alpha_val(x, _y);
1021 _image.set_alpha_val(x, _y, v);
1027 INLINE PNMImage::CRow::
1028 CRow(
const PNMImage &image,
int y) : _image(image), _y(y) {
1029 nassertv(y >= 0 && y < _image._y_size);
1037 return _image.get_x_size();
1045 return _image.get_xel_a(x, _y);
1053 return _image.get_xel_val(x, _y);
1061 return _image.get_alpha_val(x, _y);
1069 return Row(*
this, y);
1077 return CRow(*
this, y);
1122 xel *array = _array;
1135 xelval *alpha = _alpha;
1144 INLINE
void PNMImage::
1146 _array = (
xel *)PANDA_MALLOC_ARRAY((
size_t)_x_size * (size_t)_y_size *
sizeof(
xel));
1152 INLINE
void PNMImage::
1154 _alpha = (xelval *)PANDA_MALLOC_ARRAY((
size_t)_x_size * (size_t)_y_size *
sizeof(xelval));
1160 INLINE
xel *PNMImage::
1162 nassertr(y >= 0 && y < _y_size,
nullptr);
1163 return _array + y * _x_size;
1170 INLINE xelval *PNMImage::
1171 alpha_row(
int y)
const {
1172 nassertr(_alpha !=
nullptr && y >= 0 && y < _y_size,
nullptr);
1173 return _alpha + y * _x_size;
1180 INLINE
void PNMImage::
1181 setup_sub_image(
const PNMImage ©,
int &xto,
int &yto,
1182 int &xfrom,
int &yfrom,
int &x_size,
int &y_size,
1183 int &xmin,
int &ymin,
int &xmax,
int &ymax) {
1213 x_size = std::min(x_size, copy.
get_x_size() - xfrom);
1214 y_size = std::min(y_size, copy.
get_y_size() - yfrom);
1219 xmax = std::min(xmin + x_size,
get_x_size());
1220 ymax = std::min(ymin + y_size,
get_y_size());
1227 INLINE
void PNMImage::
1228 compute_spot_pixel(LColorf &c,
float d2,
1229 float min_radius,
float max_radius,
1230 const LColorf &fg,
const LColorf &bg) {
1232 if (d > max_radius) {
1234 }
else if (d > min_radius) {
1235 d = (d - min_radius) / (max_radius - min_radius);
1237 float t = (3.0f * d2) - (2.0f * d * d2);
1238 c = fg + t * (bg - fg);
1310 target *= multiplier;
void set_gray_val(int x, int y, xelval gray)
Sets the gray component color at the indicated pixel.
Row operator [](int y)
Allows the PNMImage to appear to be a 2-d array of xels.
void set_green(int x, int y, float g)
Sets the green component color only at the indicated pixel.
void set_xel_val(int x, const xel &v)
Set the pixel at the given column in the row.
size_t size() const
Get the number of pixels in the row.
xelval to_val(float input_value) const
A handy function to scale non-alpha values from [0..1] to [0..get_maxval()].
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
xelval to_alpha_val(float input_value) const
A handy function to scale alpha values from [0..1] to [0..get_maxval()].
ColorSpace get_color_space() const
Returns the color space in which the image is encoded.
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,...
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 ...
xelval get_gray_val(int x, int y) const
Returns the gray component color at the indicated pixel.
void alpha_fill(float alpha=0.0)
Sets the entire alpha channel to the given level.
void set_green_val(int x, int y, xelval g)
Sets the green component color only at the indicated pixel.
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,...
void apply_exponent(float gray_exponent)
Adjusts each channel of the image by raising the corresponding component value to the indicated expon...
LColorf operator[](int x) const
Fetch the RGB value at the given column in the row.
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...
float get_gray(int x, int y) const
Returns the gray component color at the indicated pixel.
void set_xel_val(int x, int y, const xel &value)
Changes the RGB color at the indicated pixel.
float get_blue(int x, int y) const
Returns the blue component color at the indicated pixel.
This is the base class of a family of classes that represent particular image file types that PNMImag...
void make_rgb()
Converts the image from grayscale to RGB.
xelval clamp_val(int input_value) const
A handy function to clamp values to [0..get_maxval()].
void set_color_type(ColorType color_type)
Translates the image to or from grayscale, color, or four-color mode.
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,...
xel * get_array()
Directly access the underlying PNMImage array.
xel & get_xel_val(int x)
Fetch the pixel at the given column in the row.
float from_val(xelval input_value) const
A handy function to scale non-alpha values from [0..get_maxval()] to [0..1].
void set_red(int x, int y, float r)
Sets the red component color only at the indicated pixel.
void remove_alpha()
Removes the image's alpha channel, if it exists.
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.
float get_red(int x, int y) const
Returns the red component color at the indicated pixel.
void clear_read_size()
Undoes the effect of a previous call to set_read_size().
bool is_valid() const
Returns true if the image has been read in or correctly initialized with a height and width.
xel & get_xel_val(int x, int y)
Returns the RGB color at the indicated pixel.
xelval * take_alpha_array()
Returns the underlying PNMImage array and removes it from the PNMImage.
LRGBColorf get_xel(int x, int y) const
Returns the RGB 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...
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...
LColorf get_xel_a(int x, int y) const
Returns the RGBA color at the indicated pixel.
size_t size() const
Get the number of pixels in the row.
float get_green(int x, int y) const
Returns the green component color 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 set_gray(int x, int y, float gray)
Sets the gray component color at the indicated pixel.
xelval get_blue_val(int x, int y) const
Returns the blue component color at the indicated pixel.
void set_blue(int x, int y, float b)
Sets the blue component color only at the indicated pixel.
xelval get_alpha_val(int x) const
Fetch the alpha value at the given column in the row.
void set_xel_a(int x, int y, const LColorf &value)
Changes the RGBA color at the indicated pixel.
void alpha_fill_val(xelval alpha=0)
Sets the entire alpha channel to the given level.
xel * take_array()
Returns the underlying PNMImage array and removes it from the PNMImage.
xelval * get_alpha_array()
Directly access the underlying PNMImage array of alpha values.
void gaussian_filter_from(float radius, const PNMImage ©)
Makes a resized copy of the indicated image into this one using the indicated filter.
LColorf operator[](int x) const
Fetch the RGB 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.
void box_filter_from(float radius, const PNMImage ©)
Makes a resized copy of the indicated image into this one using the indicated filter.
void add_alpha()
Adds an alpha channel to the image, if it does not already have one.
void set_red_val(int x, int y, xelval r)
Sets the red component color only at the indicated pixel.
void clear()
Frees all memory allocated for the image, and clears all its parameters (size, color,...
void set_alpha(int x, int y, float a)
Sets the alpha component color only at the indicated pixel.
xel get_xel_val(int x) const
Fetch the pixel at the given column in the row.
bool has_read_size() const
Returns true if set_read_size() has been called.
void copy_from(const PNMImage ©)
Makes this image become a copy of the other image.
void set_alpha_val(int x, int y, xelval a)
Sets the alpha component color only at the indicated pixel.
xelval get_alpha_val(int x, int y) const
Returns the alpha component color at the indicated pixel.
void fill(float red, float green, float blue)
Sets the entire image (except the alpha channel) to the given color.
void set_num_channels(int num_channels)
Changes the number of channels associated with the image.
void make_grayscale()
Converts the image from RGB to grayscale.
void set_read_size(int x_size, int y_size)
Specifies the size to we'd like to scale the image upon reading it.
float get_bright(int x, int y) const
Returns the linear brightness of the given xel, as a linearized float in the range 0....
float from_alpha_val(xelval input_value) const
A handy function to scale alpha values from [0..get_maxval()] to [0..1].
void set_xel(int x, int y, const LRGBColorf &value)
Changes the RGB color 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; ...
xelval get_green_val(int x, int y) const
Returns the green component color at the indicated pixel.
EXPCL_PANDA_PNMIMAGE unsigned char encode_sRGB_uchar(unsigned char val)
Encodes the linearized unsigned char value to an sRGB-encoded unsigned char value.
xelval get_red_val(int x, int y) const
Returns the red component color 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.
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...
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...
xelval get_alpha_val(int x) const
Fetch the alpha value at the given column in the row.
float get_alpha(int x, int y) const
Returns the alpha component color at the indicated pixel.
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...