34 PNMImage(
int x_size,
int y_size,
int num_channels, xelval maxval,
39 clear(x_size, y_size, num_channels, maxval, type, color_space);
62 INLINE
void PNMImage::
85 return (xelval)min(max(0, input_value), (
int)
get_maxval());
97 switch (_xel_encoding) {
99 case XE_generic_alpha:
102 case XE_generic_sRGB:
103 case XE_generic_sRGB_alpha:
105 (encode_sRGB_float(input_value) *
get_maxval() + 0.5f));
108 case XE_uchar_sRGB_alpha:
109 return encode_sRGB_uchar(input_value);
111 case XE_uchar_sRGB_sse2:
112 case XE_uchar_sRGB_alpha_sse2:
113 return encode_sRGB_uchar_sse2(input_value);
117 return min(max(0, (
int)((8192 * input_value) + 4096.5f)), 65535);
144 switch (_xel_encoding) {
146 case XE_generic_alpha:
147 return (
float)input_value * _inv_maxval;
149 case XE_generic_sRGB:
150 case XE_generic_sRGB_alpha:
151 return decode_sRGB_float((
float)input_value * _inv_maxval);
154 case XE_uchar_sRGB_alpha:
155 case XE_uchar_sRGB_sse2:
156 case XE_uchar_sRGB_alpha_sse2:
157 return decode_sRGB_float((
unsigned char)input_value);
161 return (input_value - 4096) * (1.f / 8192.f);
176 return (
float)input_value * _inv_maxval;
186 fill(
float red,
float green,
float blue) {
198 fill(gray, gray, gray);
239 _read_x_size = x_size;
240 _read_y_size = y_size;
241 _has_read_size =
true;
252 _has_read_size =
false;
262 return _has_read_size;
274 return _has_read_size ? _read_x_size :
get_x_size();
286 return _has_read_size ? _read_y_size :
get_y_size();
310 return (_array != NULL);
324 nassertv(num_channels >= 1 && num_channels <= 4);
380 nassertr(x >= 0 && x < _x_size && y >= 0 && y < _y_size, _array[0]);
392 nassertr(x >= 0 && x < _x_size && y >= 0 && y < _y_size, _array[0]);
407 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
422 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
423 PPM_ASSIGN(row(y)[x], r, g, b);
438 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
439 PPM_ASSIGN(row(y)[x], gray, gray, gray);
504 nassertr(_alpha != NULL && x >= 0 && x < _x_size && y >= 0 && y < _y_size, 0);
505 return alpha_row(y)[x];
519 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
520 PPM_PUTR(row(y)[x], r);
534 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
535 PPM_PUTG(row(y)[x], g);
549 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
550 PPM_PUTB(row(y)[x], b);
569 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
570 PPM_PUTB(row(y)[x], gray);
586 nassertv(_alpha != NULL && x >= 0 && x < _x_size && y >= 0 && y < _y_size);
598 nassertr(x >= 0 && x < _x_size && y >= 0 && y < _y_size,
LRGBColorf::zero());
600 const xel &col = row(y)[x];
602 switch (_xel_encoding) {
604 case XE_generic_alpha:
605 return LRGBColorf(col.r, col.g, col.b) * _inv_maxval;
607 case XE_generic_sRGB:
608 case XE_generic_sRGB_alpha:
610 decode_sRGB_float(col.r * _inv_maxval),
611 decode_sRGB_float(col.g * _inv_maxval),
612 decode_sRGB_float(col.b * _inv_maxval));
615 case XE_uchar_sRGB_alpha:
616 case XE_uchar_sRGB_sse2:
617 case XE_uchar_sRGB_alpha_sse2:
619 decode_sRGB_float((
unsigned char)col.r),
620 decode_sRGB_float((
unsigned char)col.g),
621 decode_sRGB_float((
unsigned char)col.b));
627 (
int)col.b - 4096) * (1.f / 8192.f);
642 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
644 xel &col = row(y)[x];
646 switch (_xel_encoding) {
648 case XE_generic_alpha:
657 case XE_generic_sRGB:
658 case XE_generic_sRGB_alpha:
660 (encode_sRGB_float(value[0]) *
get_maxval() + 0.5f));
662 (encode_sRGB_float(value[1]) *
get_maxval() + 0.5f));
664 (encode_sRGB_float(value[2]) *
get_maxval() + 0.5f));
668 case XE_uchar_sRGB_alpha:
669 encode_sRGB_uchar(
LColorf(value, 0.0f), col);
672 case XE_uchar_sRGB_sse2:
673 case XE_uchar_sRGB_alpha_sse2:
674 encode_sRGB_uchar_sse2(
LColorf(value, 0.0f), col);
681 col.r = min(max(0, (
int)scaled[0]), 65535);
682 col.g = min(max(0, (
int)scaled[1]), 65535);
683 col.b = min(max(0, (
int)scaled[2]), 65535);
696 set_xel(
int x,
int y,
float r,
float g,
float b) {
709 xelval val =
to_val(gray);
721 const xel &col = row(y)[x];
723 switch (_xel_encoding) {
725 return LColorf(col.r, col.g, col.b, 0.0f) * _inv_maxval;
727 case XE_generic_alpha:
728 return LColorf(col.r, col.g, col.b, alpha_row(y)[x]) * _inv_maxval;
730 case XE_generic_sRGB:
732 decode_sRGB_float(col.r * _inv_maxval),
733 decode_sRGB_float(col.g * _inv_maxval),
734 decode_sRGB_float(col.b * _inv_maxval),
737 case XE_generic_sRGB_alpha:
739 decode_sRGB_float(col.r * _inv_maxval),
740 decode_sRGB_float(col.g * _inv_maxval),
741 decode_sRGB_float(col.b * _inv_maxval),
742 alpha_row(y)[x] * _inv_maxval);
745 case XE_uchar_sRGB_sse2:
747 decode_sRGB_float((
unsigned char)col.r),
748 decode_sRGB_float((
unsigned char)col.g),
749 decode_sRGB_float((
unsigned char)col.b),
752 case XE_uchar_sRGB_alpha:
753 case XE_uchar_sRGB_alpha_sse2:
755 decode_sRGB_float((
unsigned char)col.r),
756 decode_sRGB_float((
unsigned char)col.g),
757 decode_sRGB_float((
unsigned char)col.b),
758 alpha_row(y)[x] * (1.f / 255.f));
761 return LColorf((
int)col.r - 4096,
768 static const LColorf scale(1.f / 8192.f, 1.f / 8192.f, 1.f / 8192.f, 1.f / 65535.f);
773 color.componentwise_mult(scale);
790 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
792 xel &col = row(y)[x];
794 switch (_xel_encoding) {
804 case XE_generic_alpha:
810 alpha_row(y)[x] =
clamp_val((
int)scaled[3]);
814 case XE_generic_sRGB:
816 (encode_sRGB_float(value[0]) *
get_maxval() + 0.5f));
818 (encode_sRGB_float(value[1]) *
get_maxval() + 0.5f));
820 (encode_sRGB_float(value[2]) *
get_maxval() + 0.5f));
823 case XE_generic_sRGB_alpha:
825 (encode_sRGB_float(value[0]) *
get_maxval() + 0.5f));
827 (encode_sRGB_float(value[1]) *
get_maxval() + 0.5f));
829 (encode_sRGB_float(value[2]) *
get_maxval() + 0.5f));
834 encode_sRGB_uchar(value, col);
837 case XE_uchar_sRGB_alpha:
838 encode_sRGB_uchar(value, col, alpha_row(y)[x]);
841 case XE_uchar_sRGB_sse2:
842 encode_sRGB_uchar_sse2(value, col);
845 case XE_uchar_sRGB_alpha_sse2:
846 encode_sRGB_uchar_sse2(value, col, alpha_row(y)[x]);
851 LColorf scaled = value * 8192.0f + 4096.5f;
852 col.r = min(max(0, (
int)scaled[0]), 65535);
853 col.g = min(max(0, (
int)scaled[1]), 65535);
854 col.b = min(max(0, (
int)scaled[2]), 65535);
860 LColorf scaled = value * 8192.0f + 4096.5f;
861 col.r = min(max(0, (
int)scaled[0]), 65535);
862 col.g = min(max(0, (
int)scaled[1]), 65535);
863 col.b = min(max(0, (
int)scaled[2]), 65535);
864 alpha_row(y)[x] = min(max(0, (
int)(value[3] * 65535 + 0.5f)), 65535);
877 set_xel_a(
int x,
int y,
float r,
float g,
float b,
float a) {
1021 return get_bright(x, y, _default_rc, _default_gc, _default_bc);
1046 get_bright(
int x,
int y,
float rc,
float gc,
float bc,
float ac)
const {
1061 blend(x, y, val[0], val[1], val[2], alpha);
1123 apply_exponent(gray_exponent, gray_exponent, gray_exponent, 1.0);
1135 apply_exponent(gray_exponent, gray_exponent, gray_exponent, alpha_exponent);
1150 apply_exponent(red_exponent, green_exponent, blue_exponent, 1.0);
1156 INLINE PNMImage::Row::
1157 Row(
PNMImage &image,
int y) : _image(image), _y(y) {
1158 nassertv(y >= 0 && y < _image._y_size);
1178 return _image.get_xel_a(x, _y);
1189 INLINE
void PNMImage::Row::
1190 __setitem__(
int x,
const LColorf &v) {
1191 _image.set_xel_a(x, _y, v);
1202 return _image.get_xel_val(x, _y);
1212 _image.set_xel_val(x, _y, v);
1222 return _image.get_alpha_val(x, _y);
1232 _image.set_alpha_val(x, _y, v);
1238 INLINE PNMImage::CRow::
1239 CRow(
const PNMImage &image,
int y) : _image(image), _y(y) {
1240 nassertv(y >= 0 && y < _image._y_size);
1250 return _image.get_x_size();
1260 return _image.get_xel_a(x, _y);
1270 return _image.get_xel_val(x, _y);
1280 return _image.get_alpha_val(x, _y);
1291 return Row(*
this, y);
1302 return CRow(*
this, y);
1360 xel *array = _array;
1376 xelval *alpha = _alpha;
1387 INLINE
void PNMImage::
1389 _array = (
xel *)PANDA_MALLOC_ARRAY(_x_size * _y_size *
sizeof(
xel));
1398 INLINE
void PNMImage::
1400 _alpha = (xelval *)PANDA_MALLOC_ARRAY(_x_size * _y_size *
sizeof(xelval));
1409 INLINE
xel *PNMImage::
1411 nassertr(y >= 0 && y < _y_size, NULL);
1412 return _array + y * _x_size;
1421 INLINE xelval *PNMImage::
1422 alpha_row(
int y)
const {
1423 nassertr(_alpha != NULL && y >= 0 && y < _y_size, NULL);
1424 return _alpha + y * _x_size;
1434 INLINE
void PNMImage::
1435 setup_sub_image(
const PNMImage ©,
int &xto,
int &yto,
1436 int &xfrom,
int &yfrom,
int &x_size,
int &y_size,
1437 int &xmin,
int &ymin,
int &xmax,
int &ymax) {
1467 x_size = min(x_size, copy.
get_x_size() - xfrom);
1468 y_size = min(y_size, copy.
get_y_size() - yfrom);
1484 INLINE
void PNMImage::
1485 compute_spot_pixel(
LColorf &c,
float d2,
1486 float min_radius,
float max_radius,
1489 if (d > max_radius) {
1491 }
else if (d > min_radius) {
1492 d = (d - min_radius) / (max_radius - min_radius);
1494 float t = (3.0 * d2) - (2.0 * d * d2);
1495 c = fg + t * (bg - fg);
1583 target *= multiplier;
float from_alpha_val(xelval input_value) const
A handy function to scale alpha values from [0..get_maxval()] to [0..1].
xelval clamp_val(int input_value) const
A handy function to clamp values to [0..get_maxval()].
void set_gray_val(int x, int y, xelval gray)
Sets the gray component color at the indicated pixel.
size_t size() const
Get the number of pixels in the row.
This is the base class for all three-component vectors and points.
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.
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
bool is_valid() const
Returns true if the image has been read in or correctly initialized with a height and width...
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, based on the given alpha value.
float from_val(xelval input_value) const
A handy function to scale non-alpha values from [0..get_maxval()] to [0..1].
void alpha_fill(float alpha=0.0)
Sets the entire alpha channel to the given level.
xelval to_val(float input_value) const
A handy function to scale non-alpha values from [0..1] to [0..get_maxval()].
LColorf get_xel_a(int x, int y) const
Returns the RGBA color at the indicated pixel.
void set_green_val(int x, int y, xelval g)
Sets the green component color only at the indicated pixel.
float get_red(int x, int y) const
Returns the red component color 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, converts it to an image with a gamma curve of to_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...
float get_blue(int x, int y) const
Returns the blue component color at the indicated pixel.
float get_bright(int x, int y) const
Returns the linear brightness of the given xel, as a linearized float in the range 0...
Row operator[](int y)
Allows the PNMImage to appear to be a 2-d array of xels.
void set_xel_val(int x, int y, const xel &value)
Changes the RGB color at the indicated pixel.
xelval get_blue_val(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.
float get_gray(int x, int y) const
Returns the gray component color at the indicated pixel.
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, converts it to an image with a gamma curve of to_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.
void set_red(int x, int y, float r)
Sets the red component color only at the indicated pixel.
static const LVecBase3f & zero()
Returns a zero-length vector.
float get_alpha(int x, int y) const
Returns the alpha component color at the indicated pixel.
void remove_alpha()
Removes the image's alpha channel, if it exists.
xelval get_alpha_val(int x) const
Fetch the alpha value at the given column in the row.
void clear_read_size()
Undoes the effect of a previous call to set_read_size().
xel & get_xel_val(int x, int y)
Returns the RGB color at the indicated pixel.
xelval get_green_val(int x, int y) const
Returns the green component color at the indicated pixel.
float get_green(int x, int y) const
Returns the green component color at the indicated pixel.
xelval * take_alpha_array()
Returns the underlying PNMImage array and removes it from the PNMImage.
void gaussian_filter(float radius=1.0)
This flavor of gaussian_filter() will apply the filter over the entire image without resizing or copy...
LColorf operator[](int x) const
Fetch the RGB value at the given column in the row.
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.
void set_blue(int x, int y, float b)
Sets the blue component color only at the indicated pixel.
xel get_xel_val(int x) const
Fetch the pixel at the given column in the row.
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 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.
ColorSpace get_color_space() const
Returns the color space in which the image is encoded.
xelval get_alpha_val(int x, int y) const
Returns the alpha component color at the indicated pixel.
bool has_read_size() const
Returns true if set_read_size() has been called.
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.
This is the base class for all three-component vectors and points.
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, type, etc).
void set_alpha(int x, int y, float a)
Sets the alpha component color only 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()].
xelval get_alpha_val(int x) const
Fetch the alpha 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...
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 right image is subtracted from each pixel v...
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_red_val(int x, int y) const
Returns the red component color at the indicated pixel.
LRGBColorf get_xel(int x, int y) const
Returns the RGB 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.
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...
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_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; ...
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 ...
size_t size() const
Get the number of pixels in the row.
void fill_val(xelval red, xelval green, xelval blue)
Sets the entire image (except the alpha channel) to the given color.
xelval get_gray_val(int x, int y) const
Returns the gray component color at the indicated pixel.