34 _has_read_size =
false;
36 bool result =
read(filename, type);
39 <<
"Could not read image " << filename <<
"\n";
49 if (_array !=
nullptr) {
50 PANDA_FREE_ARRAY(_array);
53 if (_alpha !=
nullptr) {
54 PANDA_FREE_ARRAY(_alpha);
61 _inv_maxval = 1.0 / 255.0;
62 _color_space = CS_linear;
65 _has_read_size =
false;
66 _xel_encoding = XE_generic;
74 clear(
int x_size,
int y_size,
int num_channels,
75 xelval maxval,
PNMFileType *type, ColorSpace color_space) {
77 nassertv(num_channels >= 1 && num_channels <= 4);
78 nassertv(color_space != CS_unspecified);
82 _num_channels = num_channels;
84 _color_space = color_space;
87 _has_read_size =
false;
91 memset(_alpha, 0,
sizeof(xelval) * _y_size * _x_size);
95 memset(_array, 0,
sizeof(
xel) * _y_size * _x_size);
111 memcpy(_alpha, copy._alpha,
sizeof(xelval) * _y_size * _x_size);
113 memcpy(_array, copy._array,
sizeof(
xel) * _y_size * _x_size);
123 nassertv(src_channel >= 0 && src_channel <= 3);
124 nassertv(dest_channel >= 0 && dest_channel <= 3);
127 pnmimage_cat.error() <<
"One of the images is invalid!\n";
132 pnmimage_cat.error() <<
"Image size doesn't match!\n";
136 for (
int x = 0; x < _x_size; x++) {
137 for (
int y = 0; y < _y_size; y++) {
140 t.set_cell(dest_channel, o.get_cell(src_channel));
156 nassertv(src_channel >= 0 && src_channel <= 3);
157 nassertv(dest_channel >= 0 && dest_channel <= 3);
160 pnmimage_cat.error() <<
"One of the images is invalid!\n";
165 pnmimage_cat.error() <<
"Image size doesn't match!\n";
170 if (right_shift >= 0) {
171 xelval dest_mask = ~(src_mask >> right_shift);
172 for (
int x = 0; x < _x_size; x++) {
173 for (
int y = 0; y < _y_size; y++) {
176 dest = (dest & dest_mask) | ((src & src_mask) >> right_shift);
181 int left_shift = -right_shift;
182 xelval dest_mask = ~(src_mask << left_shift);
183 for (
int x = 0; x < _x_size; x++) {
184 for (
int y = 0; y < _y_size; y++) {
187 dest = (dest & dest_mask) | ((src & src_mask) << left_shift);
202 PNMImageHeader::operator = (header);
207 _inv_maxval = 1.0f / (float)_maxval;
226 PNMImageHeader::operator = (orig);
231 _alpha = orig._alpha;
232 orig._alpha =
nullptr;
234 _array = orig._array;
235 orig._array =
nullptr;
244 fill_val(xelval red, xelval green, xelval blue) {
280 if (reader ==
nullptr) {
301 read(std::istream &data,
const std::string &filename,
PNMFileType *type,
302 bool report_unknown_type) {
304 (&data,
false, filename, std::string(), type, report_unknown_type);
305 if (reader ==
nullptr) {
323 int read_x_size = _read_x_size;
324 int read_y_size = _read_y_size;
328 if (reader ==
nullptr) {
352 return pfm.
store(*
this);
357 _y_size = reader->
read_data(_array, _alpha);
368 if (
has_read_size && (_x_size != read_x_size || _y_size != read_y_size)) {
391 if (writer ==
nullptr) {
395 return write(writer);
408 write(std::ostream &data,
const std::string &filename,
PNMFileType *type)
const {
414 (&data,
false, filename, type);
415 if (writer ==
nullptr) {
419 return write(writer);
431 if (writer ==
nullptr) {
446 if (!pfm.
load(*
this)) {
464 int result = writer->
write_data(_array, _alpha);
467 return (result == _y_size);
479 nassertv((
int)color_type >= 1 && (
int)color_type <= 4);
503 if (_alpha !=
nullptr) {
504 PANDA_FREE_ARRAY(_alpha);
511 memset(_alpha, 0,
sizeof(xelval) * (_x_size * _y_size));
514 _num_channels = (int)color_type;
535 nassertv(color_space != CS_unspecified);
537 if (color_space == _color_space) {
541 if (_array !=
nullptr) {
542 size_t array_size = _x_size * _y_size;
545 switch (color_space) {
547 if (_maxval == 255 && _color_space == CS_sRGB) {
548 for (
size_t i = 0; i < array_size; ++i) {
549 xel &col = _array[i];
555 for (
int x = 0; x < _x_size; ++x) {
556 for (
int y = 0; y < _y_size; ++y) {
557 LRGBColorf scaled =
get_xel(x, y) * _maxval + 0.5f;
558 xel &col = row(y)[x];
568 if (_maxval == 255 && _color_space == CS_linear) {
569 for (
size_t i = 0; i < array_size; ++i) {
570 xel &col = _array[i];
576 for (
int x = 0; x < _x_size; ++x) {
577 for (
int y = 0; y < _y_size; ++y) {
578 xel &col = row(y)[x];
586 for (
int x = 0; x < _x_size; ++x) {
587 for (
int y = 0; y < _y_size; ++y) {
588 LRGBColorf scaled =
get_xel(x, y) * 8192.f + 4096.5f;
589 xel &col = row(y)[x];
590 col.r = min(max(0, (
int)scaled[0]), 65535);
591 col.g = min(max(0, (
int)scaled[1]), 65535);
592 col.b = min(max(0, (
int)scaled[2]), 65535);
599 nassert_raise(
"invalid color space");
604 _color_space = color_space;
647 float r =
get_red(x, y) * alpha;
672 float r =
get_red(x, y) / alpha;
686 if (_array !=
nullptr) {
687 xel *new_array = (
xel *)PANDA_MALLOC_ARRAY(_x_size * _y_size *
sizeof(
xel));
688 for (
int y = 0; y < _y_size; y++) {
689 int new_y = _y_size - 1 - y;
690 memcpy(new_array + new_y * _x_size, _array + y * _x_size, _x_size *
sizeof(
xel));
692 PANDA_FREE_ARRAY(_array);
696 if (_alpha !=
nullptr) {
697 xelval *new_alpha = (xelval *)PANDA_MALLOC_ARRAY(_x_size * _y_size *
sizeof(xelval));
698 for (
int y = 0; y < _y_size; y++) {
699 int new_y = _y_size - 1 - y;
700 memcpy(new_alpha + new_y * _x_size, _alpha + y * _x_size, _x_size *
sizeof(xelval));
702 PANDA_FREE_ARRAY(_alpha);
715 flip(
bool flip_x,
bool flip_y,
bool transpose) {
718 if (_array !=
nullptr) {
719 xel *new_array = (
xel *)PANDA_MALLOC_ARRAY(_x_size * _y_size *
sizeof(
xel));
720 for (
int xi = 0; xi < _x_size; ++xi) {
721 xel *row = new_array + xi * _y_size;
722 int source_xi = !flip_x ? xi : _x_size - 1 - xi;
723 for (
int yi = 0; yi < _y_size; ++yi) {
724 int source_yi = !flip_y ? yi : _y_size - 1 - yi;
725 xel *source_row = _array + source_yi * _x_size;
726 row[yi] = source_row[source_xi];
729 PANDA_FREE_ARRAY(_array);
733 if (_alpha !=
nullptr) {
734 xelval *new_alpha = (xelval *)PANDA_MALLOC_ARRAY(_x_size * _y_size *
sizeof(xelval));
735 for (
int xi = 0; xi < _x_size; ++xi) {
736 xelval *row = new_alpha + xi * _y_size;
737 int source_xi = !flip_x ? xi : _x_size - 1 - xi;
738 for (
int yi = 0; yi < _y_size; ++yi) {
739 int source_yi = !flip_y ? yi : _y_size - 1 - yi;
740 xelval *source_row = _alpha + source_yi * _x_size;
741 row[yi] = source_row[source_xi];
745 PANDA_FREE_ARRAY(_alpha);
755 if (_array !=
nullptr) {
756 xel *new_array = (
xel *)PANDA_MALLOC_ARRAY(_x_size * _y_size *
sizeof(
xel));
757 for (
int yi = 0; yi < _y_size; ++yi) {
758 xel *row = new_array + yi * _x_size;
759 int source_yi = !flip_y ? yi : _y_size - 1 - yi;
760 xel *source_row = _array + source_yi * _x_size;
762 for (
int xi = 0; xi < _x_size; ++xi) {
763 int source_xi = !flip_x ? xi : _x_size - 1 - xi;
764 row[xi] = source_row[source_xi];
767 PANDA_FREE_ARRAY(_array);
771 if (_alpha !=
nullptr) {
772 xelval *new_alpha = (xelval *)PANDA_MALLOC_ARRAY(_x_size * _y_size *
sizeof(xelval));
773 for (
int yi = 0; yi < _y_size; ++yi) {
774 xelval *row = new_alpha + yi * _x_size;
775 int source_yi = !flip_y ? yi : _y_size - 1 - yi;
776 xelval *source_row = _alpha + source_yi * _x_size;
778 for (
int xi = 0; xi < _x_size; ++xi) {
779 int source_xi = !flip_x ? xi : _x_size - 1 - xi;
780 row[xi] = source_row[source_xi];
784 PANDA_FREE_ARRAY(_alpha);
795 nassertv(maxval > 0);
797 if (maxval != _maxval) {
798 float ratio = (float)maxval / (
float)_maxval;
853 <<
"Invalid request for channel " << channel <<
" in "
855 nassert_raise(
"unexpected channel count");
875 if (_num_channels == 2) {
891 nassert_raise(
"unexpected channel count");
920 <<
"Invalid request for channel " << channel <<
" in "
922 nassert_raise(
"unexpected channel count");
935 set_channel(
int x,
int y,
int channel,
float value) {
942 if (_num_channels == 2) {
958 nassert_raise(
"unexpected channel count");
969 switch (_num_channels) {
992 if (_alpha !=
nullptr) {
1004 blend(
int x,
int y,
float r,
float g,
float b,
float alpha) {
1012 }
else if (alpha > 0.0f) {
1016 if (prev_alpha == 0.0f) {
1023 LRGBColorf prev_rgb =
get_xel(x, y);
1024 r = r + (1.0f - alpha) * (prev_rgb[0] - r);
1025 g = g + (1.0f - alpha) * (prev_rgb[1] - g);
1026 b = b + (1.0f - alpha) * (prev_rgb[2] - b);
1027 alpha = prev_alpha + alpha * (1.0f - prev_alpha);
1047 if (_array !=
nullptr) {
1048 PANDA_FREE_ARRAY(_array);
1063 if (_alpha !=
nullptr) {
1064 PANDA_FREE_ARRAY(_alpha);
1078 int xfrom,
int yfrom,
int x_size,
int y_size) {
1079 int xmin, ymin, xmax, ymax;
1080 setup_sub_image(copy, xto, yto, xfrom, yfrom, x_size, y_size,
1081 xmin, ymin, xmax, ymax);
1087 for (y = ymin; y < ymax; y++) {
1088 for (x = xmin; x < xmax; x++) {
1094 for (y = ymin; y < ymax; y++) {
1095 for (x = xmin; x < xmax; x++) {
1104 for (y = ymin; y < ymax; y++) {
1105 for (x = xmin; x < xmax; x++) {
1111 for (y = ymin; y < ymax; y++) {
1112 for (x = xmin; x < xmax; x++) {
1133 int xfrom,
int yfrom,
int x_size,
int y_size,
1134 float pixel_scale) {
1135 if (!copy.
has_alpha() && pixel_scale == 1.0) {
1140 int xmin, ymin, xmax, ymax;
1141 setup_sub_image(copy, xto, yto, xfrom, yfrom, x_size, y_size,
1142 xmin, ymin, xmax, ymax);
1146 for (y = ymin; y < ymax; y++) {
1147 for (x = xmin; x < xmax; x++) {
1148 blend(x, y, copy.
get_xel(x - xmin + xfrom, y - ymin + yfrom),
1149 copy.
get_alpha(x - xmin + xfrom, y - ymin + yfrom) * pixel_scale);
1153 for (y = ymin; y < ymax; y++) {
1154 for (x = xmin; x < xmax; x++) {
1155 blend(x, y, copy.
get_xel(x - xmin + xfrom, y - ymin + yfrom),
1169 int xfrom,
int yfrom,
int x_size,
int y_size,
1170 float pixel_scale) {
1171 int xmin, ymin, xmax, ymax;
1172 setup_sub_image(copy, xto, yto, xfrom, yfrom, x_size, y_size,
1173 xmin, ymin, xmax, ymax);
1177 for (y = ymin; y < ymax; y++) {
1178 for (x = xmin; x < xmax; x++) {
1184 for (y = ymin; y < ymax; y++) {
1185 for (x = xmin; x < xmax; x++) {
1186 LRGBColorf rgb1 =
get_xel(x, y);
1187 LRGBColorf rgb2 = copy.
get_xel(x - xmin + xfrom, y - ymin + yfrom);
1189 rgb1[0] + rgb2[0] * pixel_scale,
1190 rgb1[1] + rgb2[1] * pixel_scale,
1191 rgb1[2] + rgb2[2] * pixel_scale);
1203 int xfrom,
int yfrom,
int x_size,
int y_size,
1204 float pixel_scale) {
1205 int xmin, ymin, xmax, ymax;
1206 setup_sub_image(copy, xto, yto, xfrom, yfrom, x_size, y_size,
1207 xmin, ymin, xmax, ymax);
1211 for (y = ymin; y < ymax; y++) {
1212 for (x = xmin; x < xmax; x++) {
1218 for (y = ymin; y < ymax; y++) {
1219 for (x = xmin; x < xmax; x++) {
1220 LRGBColorf rgb1 =
get_xel(x, y);
1221 LRGBColorf rgb2 = copy.
get_xel(x - xmin + xfrom, y - ymin + yfrom);
1223 rgb1[0] * rgb2[0] * pixel_scale,
1224 rgb1[1] * rgb2[1] * pixel_scale,
1225 rgb1[2] * rgb2[2] * pixel_scale);
1242 int xfrom,
int yfrom,
int x_size,
int y_size,
1243 float pixel_scale) {
1244 int xmin, ymin, xmax, ymax;
1245 setup_sub_image(copy, xto, yto, xfrom, yfrom, x_size, y_size,
1246 xmin, ymin, xmax, ymax);
1252 for (y = ymin; y < ymax; y++) {
1253 for (x = xmin; x < xmax; x++) {
1257 PPM_ASSIGN(p, min(c.r, o.r), min(c.g, o.g), min(c.b, o.b));
1263 for (y = ymin; y < ymax; y++) {
1264 for (x = xmin; x < xmax; x++) {
1265 xelval c = copy.
get_alpha_val(x - xmin + xfrom, y - ymin + yfrom);
1275 for (y = ymin; y < ymax; y++) {
1276 for (x = xmin; x < xmax; x++) {
1277 LRGBColorf c = copy.
get_xel(x - xmin + xfrom, y - ymin + yfrom);
1280 p.set(min(1.0f - ((1.0f - c[0]) * pixel_scale), o[0]),
1281 min(1.0f - ((1.0f - c[1]) * pixel_scale), o[1]),
1282 min(1.0f - ((1.0f - c[2]) * pixel_scale), o[2]));
1288 for (y = ymin; y < ymax; y++) {
1289 for (x = xmin; x < xmax; x++) {
1290 float c = copy.
get_alpha(x - xmin + xfrom, y - ymin + yfrom);
1292 set_alpha(x, y, min(1.0f - ((1.0f - c) * pixel_scale), o));
1309 int xfrom,
int yfrom,
int x_size,
int y_size,
1310 float pixel_scale) {
1311 int xmin, ymin, xmax, ymax;
1312 setup_sub_image(copy, xto, yto, xfrom, yfrom, x_size, y_size,
1313 xmin, ymin, xmax, ymax);
1319 for (y = ymin; y < ymax; y++) {
1320 for (x = xmin; x < xmax; x++) {
1324 PPM_ASSIGN(p, max(c.r, o.r), max(c.g, o.g), max(c.b, o.b));
1330 for (y = ymin; y < ymax; y++) {
1331 for (x = xmin; x < xmax; x++) {
1332 xelval c = copy.
get_alpha_val(x - xmin + xfrom, y - ymin + yfrom);
1342 for (y = ymin; y < ymax; y++) {
1343 for (x = xmin; x < xmax; x++) {
1344 LRGBColorf c = copy.
get_xel(x - xmin + xfrom, y - ymin + yfrom);
1347 p.set(max(c[0] * pixel_scale, o[0]),
1348 max(c[1] * pixel_scale, o[1]),
1349 max(c[2] * pixel_scale, o[2]));
1355 for (y = ymin; y < ymax; y++) {
1356 for (x = xmin; x < xmax; x++) {
1357 float c = copy.
get_alpha(x - xmin + xfrom, y - ymin + yfrom);
1359 set_alpha(x, y, max(c * pixel_scale, o));
1396 xelval lt_alpha = 0;
1403 (xelval)(PPM_GETR(lt_val) * scale + 0.5),
1404 (xelval)(PPM_GETG(lt_val) * scale + 0.5),
1405 (xelval)(PPM_GETB(lt_val) * scale + 0.5));
1406 lt_alpha = (xelval)(lt_alpha * scale + 0.5);
1410 xelval ge_alpha = 0;
1417 (xelval)(PPM_GETR(ge_val) * scale + 0.5),
1418 (xelval)(PPM_GETG(ge_val) * scale + 0.5),
1419 (xelval)(PPM_GETB(ge_val) * scale + 0.5));
1420 ge_alpha = (xelval)(ge_alpha * scale + 0.5);
1603 nassertv(radius <= PNM_MAXMAXVAL);
1609 for (
int yi = 0; yi < mask.
get_y_size(); ++yi) {
1610 for (
int xi = 0; xi < mask.
get_x_size(); ++xi) {
1617 if (shrink_from_border) {
1619 for (
int yi = 0; yi < mask.
get_y_size(); ++yi) {
1623 for (
int xi = 0; xi < mask.
get_x_size(); ++xi) {
1647 nassertv(radius <= PNM_MAXMAXVAL);
1653 for (
int yi = 0; yi < mask.
get_y_size(); ++yi) {
1654 for (
int xi = 0; xi < mask.
get_x_size(); ++xi) {
1687 nassertv(v >= 0 && v < pixel_values.
get_x_size());
1703 rescale(
float min_val,
float max_val) {
1704 float scale = max_val - min_val;
1706 if (_num_channels <= 2) {
1711 set_gray(x, y, (val - min_val) / scale);
1720 (
xel[0] - min_val) / scale,
1721 (
xel[1] - min_val) / scale,
1722 (
xel[2] - min_val) / scale);
1734 int xfrom,
int yfrom,
int cfrom,
1735 int x_size,
int y_size) {
1736 int xmin, ymin, xmax, ymax;
1737 setup_sub_image(copy, xto, yto, xfrom, yfrom, x_size, y_size,
1738 xmin, ymin, xmax, ymax);
1744 for (y = ymin; y < ymax; y++) {
1745 if (cto == 3 && cfrom == 3) {
1747 for (x = xmin; x < xmax; x++) {
1750 }
else if (cto == 3 && cfrom == 0) {
1752 for (x = xmin; x < xmax; x++) {
1755 }
else if (cto == 0 && cfrom == 3) {
1757 for (x = xmin; x < xmax; x++) {
1762 for (x = xmin; x < xmax; x++) {
1771 for (y = ymin; y < ymax; y++) {
1772 for (x = xmin; x < xmax; x++) {
1790 float min_radius,
float max_radius) {
1791 if (_x_size == 0 || _y_size == 0) {
1795 float x_scale = 2.0 / _x_size;
1796 float y_scale = 2.0 / _y_size;
1800 int x_center0 = _x_size / 2;
1801 int y_center0 = _y_size / 2;
1802 int x_center1 = (_x_size + 1) / 2;
1803 int y_center1 = (_y_size + 1) / 2;
1805 float min_r2 = min_radius * min_radius;
1806 float max_r2 = max_radius * max_radius;
1808 for (
int yi = 0; yi < y_center1; ++yi) {
1809 float y = yi * y_scale;
1810 float y2_inner = y * y;
1811 float y2_outer = (y + y_scale) * (y + y_scale);
1812 for (
int xi = 0; xi < x_center1; ++xi) {
1813 float x = xi * x_scale;
1814 float d2_inner = (x * x + y2_inner);
1815 float d2_outer = ((x + x_scale) * (x + x_scale) + y2_outer);
1816 float d2_a = ((x + x_scale) * (x + x_scale) + y2_inner);
1817 float d2_b = (x * x + y2_outer);
1819 if ((d2_inner <= min_r2) &&
1820 (d2_outer <= min_r2) &&
1824 set_xel_a(x_center1 - 1 - xi, y_center1 - 1 - yi, fg);
1825 set_xel_a(x_center0 + xi, y_center1 - 1 - yi, fg);
1826 set_xel_a(x_center1 - 1 - xi, y_center0 + yi, fg);
1827 set_xel_a(x_center0 + xi, y_center0 + yi, fg);
1829 }
else if ((d2_inner > max_r2) &&
1830 (d2_outer > max_r2) &&
1834 set_xel_a(x_center1 - 1 - xi, y_center1 - 1 - yi, bg);
1835 set_xel_a(x_center0 + xi, y_center1 - 1 - yi, bg);
1836 set_xel_a(x_center1 - 1 - xi, y_center0 + yi, bg);
1837 set_xel_a(x_center0 + xi, y_center0 + yi, bg);
1841 LColorf c_outer, c_inner, c_a, c_b;
1842 compute_spot_pixel(c_outer, d2_outer, min_radius, max_radius, fg, bg);
1843 compute_spot_pixel(c_inner, d2_inner, min_radius, max_radius, fg, bg);
1844 compute_spot_pixel(c_a, d2_a, min_radius, max_radius, fg, bg);
1845 compute_spot_pixel(c_b, d2_b, min_radius, max_radius, fg, bg);
1849 c = (c_outer + c_inner + c_a + c_b) * 0.25;
1851 set_xel_a(x_center1 - 1 - xi, y_center1 - 1 - yi, c);
1852 set_xel_a(x_center0 + xi, y_center1 - 1 - yi, c);
1853 set_xel_a(x_center1 - 1 - xi, y_center0 + yi, c);
1854 set_xel_a(x_center0 + xi, y_center0 + yi, c);
1868 const LColorf &color) {
1873 new_image.
fill(color[0], color[1], color[2]);
1915 int num_pixels = _x_size * _y_size;
1917 compute_histogram(hist_map, _array, _alpha);
1919 pixels.reserve(hist_map.size());
1920 HistMap::const_iterator hi;
1921 for (hi = hist_map.begin(); hi != hist_map.end(); ++hi) {
1922 if ((*hi).second <= num_pixels) {
1926 std::sort(pixels.begin(), pixels.end());
1928 histogram.
swap(pixels, hist_map);
1942 nassertv(_array !=
nullptr);
1944 size_t array_size = _x_size * _y_size;
1948 for (
size_t i = 0; i < array_size; ++i) {
1949 color_map[_array[i]];
1952 size_t num_colors = color_map.size();
1953 if (num_colors <= max_colors) {
1959 xel *colors = (
xel *)alloca(num_colors *
sizeof(
xel));
1962 it != color_map.end(); ++it) {
1963 colors[i++] = it->first;
1965 nassertv(i == num_colors);
1968 r_quantize(color_map, max_colors, colors, num_colors);
1971 for (
size_t i = 0; i < array_size; ++i) {
1972 _array[i] = color_map[_array[i]];
1986 PerlinNoise2 perlin (sx * _x_size, sy * _y_size, table_size, seed);
1987 for (x = 0; x < _x_size; ++x) {
1988 for (y = 0; y < _y_size; ++y) {
1989 noise = perlin.
noise(x, y);
1990 set_xel(x, y, 0.5 * (noise + 1.0));
2003 for (x = 0; x < _x_size; ++x) {
2004 for (y = 0; y < _y_size; ++y) {
2005 noise = perlin.
noise(x / (
float) _x_size, y / (
float) _y_size);
2006 set_xel(x, y, 0.5 * (noise + 1.0));
2018 nassertv((nchannels >= 3) && (nchannels <= 4));
2022 LVector3 outv(conv.xform_point(inv));
2023 set_xel(x, y, outv[0], outv[1], outv[2]);
2035 apply_exponent(
float red_exponent,
float green_exponent,
float blue_exponent,
2036 float alpha_exponent) {
2037 int num_channels = _num_channels;
2038 if (
has_alpha() && alpha_exponent == 1.0f) {
2045 if (red_exponent == 1.0f && green_exponent == 1.0f && blue_exponent == 1.0f) {
2047 switch (num_channels) {
2054 for (y = 0; y < _y_size; ++y) {
2055 for (x = 0; x < _x_size; ++x) {
2057 alpha = cpow(alpha, blue_exponent);
2067 switch (num_channels) {
2069 for (y = 0; y < _y_size; ++y) {
2070 for (x = 0; x < _x_size; ++x) {
2072 gray = cpow(gray, blue_exponent);
2079 for (y = 0; y < _y_size; ++y) {
2080 for (x = 0; x < _x_size; ++x) {
2082 gray = cpow(gray, blue_exponent);
2086 alpha = cpow(alpha, blue_exponent);
2093 for (y = 0; y < _y_size; ++y) {
2094 for (x = 0; x < _x_size; ++x) {
2095 LRGBColorf color =
get_xel(x, y);
2096 color[0] = cpow(color[0], red_exponent);
2097 color[1] = cpow(color[1], green_exponent);
2098 color[2] = cpow(color[2], blue_exponent);
2105 for (y = 0; y < _y_size; ++y) {
2106 for (x = 0; x < _x_size; ++x) {
2108 color[0] = cpow(color[0], red_exponent);
2109 color[1] = cpow(color[1], green_exponent);
2110 color[2] = cpow(color[2], blue_exponent);
2111 color[3] = cpow(color[3], alpha_exponent);
2132 _default_rc = lumin_red;
2133 _default_gc = lumin_grn;
2134 _default_bc = lumin_blu;
2149 _inv_maxval = 1.0f / (float)_maxval;
2153 switch (_color_space) {
2155 _xel_encoding = XE_generic_alpha;
2160 if (has_sse2_sRGB_encode()) {
2161 _xel_encoding = XE_uchar_sRGB_alpha_sse2;
2163 _xel_encoding = XE_uchar_sRGB_alpha;
2166 _xel_encoding = XE_generic_sRGB_alpha;
2171 _xel_encoding = XE_scRGB_alpha;
2176 nassert_raise(
"invalid color space");
2180 switch (_color_space) {
2182 _xel_encoding = XE_generic;
2187 if (has_sse2_sRGB_encode()) {
2188 _xel_encoding = XE_uchar_sRGB_sse2;
2190 _xel_encoding = XE_uchar_sRGB;
2193 _xel_encoding = XE_generic_sRGB;
2198 _xel_encoding = XE_scRGB;
2203 nassert_raise(
"invalid color space");
2214 xel *colors,
size_t num_colors) {
2215 if (num_colors <= max_colors) {
2217 for (
size_t i = 0; i < num_colors; ++i) {
2218 const xel &col = colors[i];
2219 color_map[col] = col;
2223 else if (max_colors == 1) {
2226 for (
size_t i = 0; i < num_colors; ++i) {
2229 avg *= 1.0f / num_colors;
2233 for (
size_t i = 0; i < num_colors; ++i) {
2234 color_map[colors[i]] = avg_val;
2238 else if (max_colors == 0) {
2245 xelval min_r = _maxval;
2246 xelval min_g = _maxval;
2247 xelval min_b = _maxval;
2248 xelval max_r = 0, max_g = 0, max_b = 0;
2249 for (
size_t i = 0; i < num_colors; ++i) {
2250 const xel &col = colors[i];
2251 min_r = std::min(min_r, col.r);
2252 max_r = std::max(max_r, col.r);
2253 min_g = std::min(min_g, col.g);
2254 max_g = std::max(max_g, col.g);
2255 min_b = std::min(min_b, col.b);
2256 max_b = std::max(max_b, col.b);
2259 int diff_r = max_r - min_r;
2260 int diff_g = max_g - min_g;
2261 int diff_b = max_b - min_b;
2263 auto sort_by_red = [](
const xel &c1,
const xel &c2) {
2266 auto sort_by_green = [](
const xel &c1,
const xel &c2) {
2269 auto sort_by_blue = [](
const xel &c1,
const xel &c2) {
2274 if (diff_g >= diff_r) {
2275 if (diff_g >= diff_b) {
2276 std::sort(colors, colors + num_colors, sort_by_green);
2278 std::sort(colors, colors + num_colors, sort_by_blue);
2280 }
else if (diff_r >= diff_b) {
2281 std::sort(colors, colors + num_colors, sort_by_red);
2283 std::sort(colors, colors + num_colors, sort_by_blue);
2287 size_t max_colors_1 = max_colors / 2;
2288 size_t max_colors_2 = max_colors - max_colors_1;
2289 size_t num_colors_1 = num_colors / 2;
2290 size_t num_colors_2 = num_colors - num_colors_1;
2291 r_quantize(color_map, max_colors_1, colors, num_colors_1);
2292 r_quantize(color_map, max_colors_2, colors + num_colors_1, num_colors_2);
2321 LRGBColorf color (LRGBColorf::zero());
2322 if (_x_size == 0 || _y_size == 0) {
2326 float factor = 1.0f / (float)(_x_size * _y_size);
2329 for (x = 0; x < _x_size; ++x) {
2330 for (y = 0; y < _y_size; ++y) {
2331 color +=
get_xel(x, y) * factor;
2344 LColorf color (LColorf::zero());
2345 if (_x_size == 0 || _y_size == 0) {
2349 float factor = 1.0f / (float)(_x_size * _y_size);
2352 for (x = 0; x < _x_size; ++x) {
2353 for (y = 0; y < _y_size; ++y) {
2367 if (_x_size == 0 || _y_size == 0) {
2372 for (x = 0; x < _x_size; ++x) {
2373 for (y = 0; y < _y_size; ++y) {
2378 gray /= (float)(_x_size * _y_size);
2389 size_t array_size = _x_size * _y_size;
2391 if (_array !=
nullptr && _alpha !=
nullptr) {
2392 for (
size_t i = 0; i < array_size; ++i) {
2393 target._array[i].r = _maxval - _array[i].r;
2394 target._array[i].g = _maxval - _array[i].g;
2395 target._array[i].b = _maxval - _array[i].b;
2396 target._alpha[i] = _maxval - _alpha[i];
2398 }
else if (_array !=
nullptr) {
2399 for (
size_t i = 0; i < array_size; ++i) {
2400 target._array[i].r = _maxval - _array[i].r;
2401 target._array[i].g = _maxval - _array[i].g;
2402 target._array[i].b = _maxval - _array[i].b;
2404 }
else if (_alpha !=
nullptr) {
2405 for (
size_t i = 0; i < array_size; ++i) {
2406 target._alpha[i] = _maxval - _alpha[i];
2419 nassertv(_x_size == other._x_size && _y_size == other._y_size);
2424 size_t array_size = _x_size * _y_size;
2427 if (_alpha !=
nullptr && other._alpha !=
nullptr) {
2428 for (
size_t i = 0; i < array_size; ++i) {
2429 _array[i].r =
clamp_val((
int)_array[i].r + (
int)other._array[i].r);
2430 _array[i].g =
clamp_val((
int)_array[i].g + (
int)other._array[i].g);
2431 _array[i].b =
clamp_val((
int)_array[i].b + (
int)other._array[i].b);
2432 _alpha[i] =
clamp_val((
int)_alpha[i] + (
int)other._alpha[i]);
2435 for (
size_t i = 0; i < array_size; ++i) {
2436 _array[i].r =
clamp_val((
int)_array[i].r + (
int)other._array[i].r);
2437 _array[i].g =
clamp_val((
int)_array[i].g + (
int)other._array[i].g);
2438 _array[i].b =
clamp_val((
int)_array[i].b + (
int)other._array[i].b);
2444 for (x = 0; x < _x_size; ++x) {
2445 for (y = 0; y < _y_size; ++y) {
2460 size_t array_size = _x_size * _y_size;
2463 int add_r = (int)(other.get_x() *
get_maxval() + 0.5);
2464 int add_g = (int)(other.get_y() *
get_maxval() + 0.5);
2465 int add_b = (int)(other.get_z() *
get_maxval() + 0.5);
2466 int add_a = (int)(other.get_w() *
get_maxval() + 0.5);
2468 if (_alpha !=
nullptr) {
2469 for (
size_t i = 0; i < array_size; ++i) {
2470 _array[i].r =
clamp_val((
int)_array[i].r + add_r);
2471 _array[i].g =
clamp_val((
int)_array[i].g + add_g);
2472 _array[i].b =
clamp_val((
int)_array[i].b + add_b);
2473 _alpha[i] =
clamp_val((
int)_alpha[i] + add_a);
2477 for (
size_t i = 0; i < array_size; ++i) {
2478 _array[i].r =
clamp_val((
int)_array[i].r + add_r);
2479 _array[i].g =
clamp_val((
int)_array[i].g + add_g);
2480 _array[i].b =
clamp_val((
int)_array[i].b + add_b);
2486 for (x = 0; x < _x_size; ++x) {
2487 for (y = 0; y < _y_size; ++y) {
2501 nassertv(_x_size == other._x_size && _y_size == other._y_size);
2506 size_t array_size = _x_size * _y_size;
2509 if (_alpha !=
nullptr && other._alpha !=
nullptr) {
2510 for (
size_t i = 0; i < array_size; ++i) {
2511 _array[i].r =
clamp_val((
int)_array[i].r - (
int)other._array[i].r);
2512 _array[i].g =
clamp_val((
int)_array[i].g - (
int)other._array[i].g);
2513 _array[i].b =
clamp_val((
int)_array[i].b - (
int)other._array[i].b);
2514 _alpha[i] =
clamp_val((
int)_alpha[i] - (
int)other._alpha[i]);
2517 for (
size_t i = 0; i < array_size; ++i) {
2518 _array[i].r =
clamp_val((
int)_array[i].r - (
int)other._array[i].r);
2519 _array[i].g =
clamp_val((
int)_array[i].g - (
int)other._array[i].g);
2520 _array[i].b =
clamp_val((
int)_array[i].b - (
int)other._array[i].b);
2526 for (x = 0; x < _x_size; ++x) {
2527 for (y = 0; y < _y_size; ++y) {
2551 nassertv(_x_size == other._x_size && _y_size == other._y_size);
2554 for (x = 0; x < _x_size; ++x) {
2555 for (y = 0; y < _y_size; ++y) {
2570 size_t array_size = _x_size * _y_size;
2572 if (_alpha !=
nullptr) {
2573 for (
size_t i = 0; i < array_size; ++i) {
2574 _array[i].r =
clamp_val((
int)(_array[i].r * multiplier + 0.5f));
2575 _array[i].g =
clamp_val((
int)(_array[i].g * multiplier + 0.5f));
2576 _array[i].b =
clamp_val((
int)(_array[i].b * multiplier + 0.5f));
2577 _alpha[i] =
clamp_val((
int)(_alpha[i] * multiplier + 0.5f));
2581 for (
size_t i = 0; i < array_size; ++i) {
2582 _array[i].r =
clamp_val((
int)(_array[i].r * multiplier + 0.5f));
2583 _array[i].g =
clamp_val((
int)(_array[i].g * multiplier + 0.5f));
2584 _array[i].b =
clamp_val((
int)(_array[i].b * multiplier + 0.5f));
2590 for (x = 0; x < _x_size; ++x) {
2591 for (y = 0; y < _y_size; ++y) {
2607 size_t array_size = _x_size * _y_size;
2609 if (_alpha !=
nullptr) {
2610 for (
size_t i = 0; i < array_size; ++i) {
2611 _array[i].r =
clamp_val((
int)(_array[i].r * other[0] + 0.5f));
2612 _array[i].g =
clamp_val((
int)(_array[i].g * other[1] + 0.5f));
2613 _array[i].b =
clamp_val((
int)(_array[i].b * other[2] + 0.5f));
2614 _alpha[i] =
clamp_val((
int)(_alpha[i] * other[3] + 0.5f));
2618 for (
size_t i = 0; i < array_size; ++i) {
2619 _array[i].r =
clamp_val((
int)(_array[i].r * other[0] + 0.5f));
2620 _array[i].g =
clamp_val((
int)(_array[i].g * other[1] + 0.5f));
2621 _array[i].b =
clamp_val((
int)(_array[i].b * other[2] + 0.5f));
2627 for (x = 0; x < _x_size; ++x) {
2628 for (y = 0; y < _y_size; ++y) {
2630 color.componentwise_mult(other);