15 #include "config_pnmimage.h"
17 #include "virtualFileSystem.h"
18 #include "pandaFileStream.h"
19 #include "littleEndian.h"
20 #include "bigEndian.h"
23 #include "pnmReader.h"
24 #include "pnmWriter.h"
25 #include "string_utils.h"
35 _has_no_data_value =
false;
36 _has_no_data_threshold =
false;
38 _has_point = has_point_noop;
52 _has_no_data_value(copy._has_no_data_value),
53 _has_no_data_threshold(copy._has_no_data_threshold),
54 _no_data_value(copy._no_data_value),
55 _has_point(copy._has_point)
65 operator = (
const PfmFile ©) {
66 PNMImageHeader::operator = (copy);
69 _has_no_data_value = copy._has_no_data_value;
70 _has_no_data_threshold = copy._has_no_data_threshold;
71 _no_data_value = copy._no_data_value;
72 _has_point = copy._has_point;
99 clear(
int x_size,
int y_size,
int num_channels) {
100 nassertv(x_size >= 0 && y_size >= 0);
101 nassertv(num_channels > 0 && num_channels <= 4 || (x_size == 0 && y_size == 0 && num_channels == 0));
106 _num_channels = num_channels;
109 int size = _x_size * _y_size * _num_channels;
114 _table.insert(_table.end(), size + 4, (PN_float32)0.0);
133 Filename filename = Filename::binary_filename(fullpath);
138 <<
"Could not find " << fullpath <<
"\n";
142 if (pnmimage_cat.is_debug()) {
144 <<
"Reading PFM file " << filename <<
"\n";
147 istream *in = file->open_read_file(
true);
148 bool success =
read(*in, fullpath);
186 if (reader == NULL) {
198 if (!pnm.
read(reader)) {
205 bool success = reader->
read_pfm(*
this);
225 <<
"PFM file is invalid.\n";
229 Filename filename = Filename::binary_filename(fullpath);
233 <<
"Unable to open " << filename <<
"\n";
237 if (pnmimage_cat.is_debug()) {
239 <<
"Writing PFM file " << filename <<
"\n";
242 return write(out, fullpath);
262 return write(writer);
275 if (writer == NULL) {
290 if (!
store(pnmimage)) {
321 switch (num_channels) {
324 for (
int yi = 0; yi < pnmimage.
get_y_size(); ++yi) {
325 for (
int xi = 0; xi < pnmimage.
get_x_size(); ++xi) {
326 _table[yi * _x_size + xi] = pnmimage.
get_gray(xi, yi);
334 for (
int yi = 0; yi < pnmimage.
get_y_size(); ++yi) {
335 for (
int xi = 0; xi < pnmimage.
get_x_size(); ++xi) {
336 PN_float32 *point = &_table[(yi * _x_size + xi) * _num_channels];
337 point[0] = pnmimage.
get_gray(xi, yi);
346 for (
int yi = 0; yi < pnmimage.
get_y_size(); ++yi) {
347 for (
int xi = 0; xi < pnmimage.
get_x_size(); ++xi) {
348 PN_float32 *point = &_table[(yi * _x_size + xi) * _num_channels];
360 for (
int yi = 0; yi < pnmimage.
get_y_size(); ++yi) {
361 for (
int xi = 0; xi < pnmimage.
get_x_size(); ++xi) {
362 PN_float32 *point = &_table[(yi * _x_size + xi) * _num_channels];
374 nassertr(
false,
false);
395 switch (num_channels) {
400 pnmimage.
set_gray(xi, yi, _table[yi * _x_size + xi]);
411 pnmimage.
set_gray(xi, yi, point[0]);
423 pnmimage.
set_xel(xi, yi, point[0], point[1], point[2]);
434 pnmimage.
set_xel_a(xi, yi, point[0], point[1], point[2], point[3]);
441 nassertr(
false,
false);
477 switch (_num_channels) {
480 for (
int yi = 0; yi < _y_size; ++yi) {
481 for (
int xi = 0; xi < _x_size; ++xi) {
482 _table[(yi * _x_size + xi)] = value[0];
490 for (
int yi = 0; yi < _y_size; ++yi) {
491 for (
int xi = 0; xi < _x_size; ++xi) {
492 (*(
LPoint2f *)&_table[(yi * _x_size + xi) * _num_channels]).set(value[0], value[1]);
500 for (
int yi = 0; yi < _y_size; ++yi) {
501 for (
int xi = 0; xi < _x_size; ++xi) {
502 (*(
LPoint3f *)&_table[(yi * _x_size + xi) * _num_channels]).set(value[0], value[1], value[2]);
510 for (
int yi = 0; yi < _y_size; ++yi) {
511 for (
int xi = 0; xi < _x_size; ++xi) {
512 *(
LPoint4f *)&_table[(yi * _x_size + xi) * _num_channels] = value;
527 PN_float32 nan = make_nan((PN_float32)0.0);
540 fill(_no_data_value);
551 nassertv(channel >= 0 && channel < _num_channels);
553 for (
int yi = 0; yi < _y_size; ++yi) {
554 for (
int xi = 0; xi < _x_size; ++xi) {
555 _table[(yi * _x_size + xi) * _num_channels + channel] = value;
568 PN_float32 nan = make_nan((PN_float32)0.0);
581 nassertv(channel >= 0 && channel < _num_channels);
583 if (!_has_no_data_value) {
586 for (
int yi = 0; yi < _y_size; ++yi) {
587 for (
int xi = 0; xi < _x_size; ++xi) {
589 _table[(yi * _x_size + xi) * _num_channels + channel] = value;
605 PN_float32 nan = make_nan((PN_float32)0.0);
623 int min_x = int(ceil(x - radius));
624 int min_y = int(ceil(y - radius));
625 int max_x = int(floor(x + radius));
626 int max_y = int(floor(y + radius));
632 int x_size = max_x - min_x + 1;
633 int y_size = max_y - min_y + 1;
634 int size = x_size * y_size;
640 mini_grid.insert(mini_grid.end(), size, MiniGridCell());
644 min_x = max(min_x, 0);
645 min_y = max(min_y, 0);
646 max_x = min(max_x, _x_size - 1);
647 max_y = min(max_y, _y_size - 1);
649 bool got_any =
false;
651 for (yi = min_y; yi <= max_y; ++yi) {
652 for (xi = min_x; xi <= max_x; ++xi) {
658 int gi = (yi - min_y) * y_size + (xi - min_x);
659 nassertr(gi >= 0 && gi < size,
false);
660 mini_grid[gi]._sxi = xi;
661 mini_grid[gi]._syi = yi;
662 mini_grid[gi]._dist = 0;
672 for (yi = 0; yi < y_size; ++yi) {
673 for (xi = 0; xi < x_size; ++xi) {
674 int gi = yi * x_size + xi;
675 if (mini_grid[gi]._dist == 0) {
676 int sxi = mini_grid[gi]._sxi;
677 int syi = mini_grid[gi]._syi;
678 fill_mini_grid(&mini_grid[0], x_size, y_size, xi + 1, yi, 1, sxi, syi);
679 fill_mini_grid(&mini_grid[0], x_size, y_size, xi - 1, yi, 1, sxi, syi);
680 fill_mini_grid(&mini_grid[0], x_size, y_size, xi, yi + 1, 1, sxi, syi);
681 fill_mini_grid(&mini_grid[0], x_size, y_size, xi, yi - 1, 1, sxi, syi);
688 for (
int gi = 0; gi < size; ++gi) {
689 int sxi = mini_grid[gi]._sxi;
690 int syi = mini_grid[gi]._syi;
695 result /= PN_float32(size);
711 x = (x * _x_size - 0.5);
712 y = (y * _y_size - 0.5);
714 int min_x = int(floor(x));
715 int min_y = int(floor(y));
717 PN_float32 frac_x = x - min_x;
718 PN_float32 frac_y = y - min_y;
721 PN_float32 w00 = 0.0, w01 = 0.0, w10 = 0.0, w11 = 0.0;
724 w00 = (1.0 - frac_y) * (1.0 - frac_x);
728 w10 = (1.0 - frac_y) * frac_x;
732 w01 = frac_y * (1.0 - frac_x);
736 w11 = frac_y * frac_x;
740 PN_float32 net_w = w00 + w01 + w10 + w11;
745 result = (p00 * w00 + p01 * w01 + p10 * w10 + p11 * w11) / net_w;
760 bool any_points =
false;
765 for (
int yi = 0; yi < _y_size; ++yi) {
766 for (
int xi = 0; xi < _x_size; ++xi) {
777 min_depth[0] = min(min_depth[0], p[0]);
778 min_depth[1] = min(min_depth[1], p[1]);
779 min_depth[2] = min(min_depth[2], p[2]);
780 max_depth[0] = max(max_depth[0], p[0]);
781 max_depth[1] = max(max_depth[1], p[1]);
782 max_depth[2] = max(max_depth[2], p[2]);
804 if (y_begin >= _y_size) {
806 x_begin = x_end = y_begin = y_end = 0;
814 nassertr(y_end > y_begin,
false);
821 nassertr(x_begin < _x_size,
false);
827 nassertr(x_end > x_begin,
false);
842 nassertr(y >= 0 && y < _y_size &&
843 x_begin >= 0 && x_begin <= x_end && x_end <= _x_size,
false);
845 if (!_has_no_data_value) {
848 for (
int x = x_begin; x < x_end; ++x) {
866 nassertr(x >= 0 && x < _x_size &&
867 y_begin >= 0 && y_begin <= y_end && y_end <= _y_size,
false);
869 if (!_has_no_data_value) {
872 for (
int y = y_begin; y < y_end; ++y) {
894 if (num_channels > 0) {
895 num_channels = min(num_channels, _num_channels);
896 _has_no_data_value =
true;
897 _has_no_data_threshold =
false;
899 PN_float32 nan = make_nan((PN_float32)0.0);
900 for (
int i = 0; i < num_channels; ++i) {
901 _no_data_value[i] = nan;
903 switch (num_channels) {
905 _has_point = has_point_nan_1;
908 _has_point = has_point_nan_2;
911 _has_point = has_point_nan_3;
914 _has_point = has_point_nan_4;
932 nassertv(is_valid());
934 _has_no_data_value =
true;
935 _has_no_data_threshold =
false;
936 _no_data_value = no_data_value;
937 switch (_num_channels) {
939 _has_point = has_point_1;
942 _has_point = has_point_2;
945 _has_point = has_point_3;
948 _has_point = has_point_4;
964 nassertv(is_valid());
966 _has_no_data_value =
true;
967 _has_no_data_threshold =
true;
968 _no_data_value = no_data_value;
969 switch (_num_channels) {
971 _has_point = has_point_threshold_1;
974 _has_point = has_point_threshold_2;
977 _has_point = has_point_threshold_3;
980 _has_point = has_point_threshold_4;
997 if (_x_size == 0 || _y_size == 0 || new_x_size == 0 || new_y_size == 0) {
998 clear(new_x_size, new_y_size, _num_channels);
1002 if (new_x_size == _x_size && new_y_size == _y_size) {
1007 result.
clear(new_x_size, new_y_size, _num_channels);
1008 if (_has_no_data_value) {
1009 result.
fill(_no_data_value);
1012 if (pfm_resize_quick && new_x_size <= _x_size && new_y_size <= _y_size) {
1019 if (pfm_resize_gaussian) {
1026 _table.swap(result._table);
1027 _x_size = new_x_size;
1028 _y_size = new_y_size;
1042 if (_x_size == 0 || _y_size == 0) {
1047 new_data.reserve(_table.size());
1049 PN_float32 from_x0, from_x1, from_y0, from_y1;
1054 PN_float32 x_scale = 1.0;
1055 PN_float32 y_scale = 1.0;
1058 x_scale = (PN_float32)orig_x_size / (PN_float32)_x_size;
1061 y_scale = (PN_float32)orig_y_size / (PN_float32)_y_size;
1064 switch (_num_channels) {
1068 for (
int to_y = 0; to_y < _y_size; ++to_y) {
1069 from_y1 = (to_y + 1.0) * y_scale;
1070 from_y1 = min(from_y1, (PN_float32)orig_y_size);
1073 for (
int to_x = 0; to_x < _x_size; ++to_x) {
1074 from_x1 = (to_x + 1.0) * x_scale;
1075 from_x1 = min(from_x1, (PN_float32)orig_x_size);
1080 from.box_filter_region(result, from_x0, from_y0, from_x1, from_y1);
1081 new_data.push_back(result);
1093 for (
int to_y = 0; to_y < _y_size; ++to_y) {
1094 from_y1 = (to_y + 1.0) * y_scale;
1095 from_y1 = min(from_y1, (PN_float32)orig_y_size);
1098 for (
int to_x = 0; to_x < _x_size; ++to_x) {
1099 from_x1 = (to_x + 1.0) * x_scale;
1100 from_x1 = min(from_x1, (PN_float32)orig_x_size);
1105 from.box_filter_region(result, from_x0, from_y0, from_x1, from_y1);
1106 new_data.push_back(result[0]);
1107 new_data.push_back(result[1]);
1119 for (
int to_y = 0; to_y < _y_size; ++to_y) {
1120 from_y1 = (to_y + 1.0) * y_scale;
1121 from_y1 = min(from_y1, (PN_float32)orig_y_size);
1124 for (
int to_x = 0; to_x < _x_size; ++to_x) {
1125 from_x1 = (to_x + 1.0) * x_scale;
1126 from_x1 = min(from_x1, (PN_float32)orig_x_size);
1131 from.box_filter_region(result, from_x0, from_y0, from_x1, from_y1);
1132 new_data.push_back(result[0]);
1133 new_data.push_back(result[1]);
1134 new_data.push_back(result[2]);
1146 for (
int to_y = 0; to_y < _y_size; ++to_y) {
1147 from_y1 = (to_y + 1.0) * y_scale;
1148 from_y1 = min(from_y1, (PN_float32)orig_y_size);
1151 for (
int to_x = 0; to_x < _x_size; ++to_x) {
1152 from_x1 = (to_x + 1.0) * x_scale;
1153 from_x1 = min(from_x1, (PN_float32)orig_x_size);
1158 from.box_filter_region(result, from_x0, from_y0, from_x1, from_y1);
1159 new_data.push_back(result[0]);
1160 new_data.push_back(result[1]);
1161 new_data.push_back(result[2]);
1162 new_data.push_back(result[3]);
1175 new_data.push_back(0.0);
1176 new_data.push_back(0.0);
1177 new_data.push_back(0.0);
1178 new_data.push_back(0.0);
1180 nassertv(new_data.size() == _table.size());
1181 _table.swap(new_data);
1191 nassertv(is_valid());
1194 reversed.reserve(_table.size());
1195 int row_size = _x_size * _num_channels;
1196 for (
int yi = 0; yi < _y_size; ++yi) {
1197 int source_yi = _y_size - 1 - yi;
1198 int start = source_yi * row_size;
1199 reversed.insert(reversed.end(),
1200 _table.begin() + start, _table.begin() + start + row_size);
1203 nassertv(reversed.size() <= _table.size());
1205 reversed.insert(reversed.end(), _table.size() - reversed.size(), (PN_float32)0.0);
1207 _table.swap(reversed);
1222 flip(
bool flip_x,
bool flip_y,
bool transpose) {
1223 nassertv(is_valid());
1226 flipped.reserve(_table.size());
1230 for (
int xi = 0; xi < _x_size; ++xi) {
1231 int source_xi = !flip_x ? xi : _x_size - 1 - xi;
1232 for (
int yi = 0; yi < _y_size; ++yi) {
1233 int source_yi = !flip_y ? yi : _y_size - 1 - yi;
1234 const PN_float32 *p = &_table[(source_yi * _x_size + source_xi) * _num_channels];
1235 for (
int ci = 0; ci < _num_channels; ++ci) {
1236 flipped.push_back(p[ci]);
1247 for (
int yi = 0; yi < _y_size; ++yi) {
1248 int source_yi = !flip_y ? yi : _y_size - 1 - yi;
1249 for (
int xi = 0; xi < _x_size; ++xi) {
1250 int source_xi = !flip_x ? xi : _x_size - 1 - xi;
1251 const PN_float32 *p = &_table[(source_yi * _x_size + source_xi) * _num_channels];
1252 for (
int ci = 0; ci < _num_channels; ++ci) {
1253 flipped.push_back(p[ci]);
1259 nassertv(flipped.size() <= _table.size());
1261 flipped.insert(flipped.end(), _table.size() - flipped.size(), (PN_float32)0.0);
1263 _table.swap(flipped);
1274 nassertv(is_valid());
1276 for (
int yi = 0; yi < _y_size; ++yi) {
1277 for (
int xi = 0; xi < _x_size; ++xi) {
1311 int working_x_size = (int)cceil(_x_size * scale_factor);
1312 int working_y_size = (int)cceil(_y_size * scale_factor);
1314 working_x_size = max(working_x_size, dist.
get_x_size());
1315 working_y_size = max(working_y_size, dist.
get_y_size());
1317 const PfmFile *source_p =
this;
1319 if ((*this).get_x_size() != working_x_size || (*this).get_y_size() != working_y_size) {
1321 scaled_source = (*this);
1322 scaled_source.
resize(working_x_size, working_y_size);
1323 source_p = &scaled_source;
1326 const PfmFile *dist_p = &dist;
1331 scaled_dist.
resize(working_x_size, working_y_size);
1332 dist_p = &scaled_dist;
1336 result.
clear(working_x_size, working_y_size, _num_channels);
1338 if (_has_no_data_value) {
1340 result.
fill(_no_data_value);
1343 for (
int yi = 0; yi < working_y_size; ++yi) {
1344 for (
int xi = 0; xi < working_x_size; ++xi) {
1350 if (!source_p->calc_bilinear_point(p, uv[0], 1.0 - uv[1])) {
1354 result.
set_point(xi, working_y_size - 1 - yi, p);
1359 result.
resize(_x_size, _y_size);
1361 nassertv(result._table.size() == _table.size());
1362 _table.swap(result._table);
1389 int working_x_size = (int)cceil(_x_size * scale_factor);
1390 int working_y_size = (int)cceil(_y_size * scale_factor);
1392 working_x_size = max(working_x_size, dist.
get_x_size());
1393 working_y_size = max(working_y_size, dist.
get_y_size());
1395 const PfmFile *source_p =
this;
1397 if ((*this).get_x_size() != working_x_size || (*this).get_y_size() != working_y_size) {
1399 scaled_source = (*this);
1400 scaled_source.
resize(working_x_size, working_y_size);
1401 source_p = &scaled_source;
1404 const PfmFile *dist_p = &dist;
1409 scaled_dist.
resize(working_x_size, working_y_size);
1410 dist_p = &scaled_dist;
1414 result.
clear(working_x_size, working_y_size, _num_channels);
1416 if (_has_no_data_value) {
1418 result.
fill(_no_data_value);
1421 for (
int yi = 0; yi < working_y_size; ++yi) {
1422 for (
int xi = 0; xi < working_x_size; ++xi) {
1423 if (!source_p->has_point(xi, yi)) {
1426 LPoint2f uv = source_p->get_point2(xi, yi);
1436 result.
resize(_x_size, _y_size);
1438 nassertv(result._table.size() == _table.size());
1439 _table.swap(result._table);
1452 nassertv(is_valid() && other.is_valid());
1453 nassertv(other._x_size == _x_size && other._y_size == _y_size);
1455 if (!_has_no_data_value) {
1460 for (
int yi = 0; yi < _y_size; ++yi) {
1461 for (
int xi = 0; xi < _x_size; ++xi) {
1478 nassertv(is_valid() && other.is_valid());
1479 nassertv(other._x_size == _x_size && other._y_size == _y_size);
1483 for (
int yi = 0; yi < _y_size; ++yi) {
1484 for (
int xi = 0; xi < _x_size; ++xi) {
1499 nassertv(is_valid() && other.is_valid());
1500 nassertv(other._x_size == _x_size && other._y_size == _y_size);
1504 for (
int yi = 0; yi < _y_size; ++yi) {
1505 for (
int xi = 0; xi < _x_size; ++xi) {
1522 nassertv(x_begin >= 0 && x_begin <= x_end && x_end <= _x_size);
1523 nassertv(y_begin >= 0 && y_begin <= y_end && y_end <= _y_size);
1525 int new_x_size = x_end - x_begin;
1526 int new_y_size = y_end - y_begin;
1528 int new_size = new_x_size * new_y_size * _num_channels;
1533 new_table.insert(new_table.end(), new_size + 4, (PN_float32)0.0);
1535 for (
int yi = 0; yi < new_y_size; ++yi) {
1536 memcpy(&new_table[(yi * new_x_size) * _num_channels],
1537 &_table[((yi + y_begin) * _x_size + x_begin) * _num_channels],
1538 new_x_size *
sizeof(PN_float32) * _num_channels);
1541 nassertv(new_table.size() == new_size + 4);
1542 _table.swap(new_table);
1543 _x_size = new_x_size;
1544 _y_size = new_y_size;
1556 clear(x_size, y_size, 3);
1560 uv_scale[0] = 1.0f / PN_float32(_x_size);
1563 uv_scale[1] = 1.0f / PN_float32(_y_size);
1566 for (
int yi = 0; yi < _y_size; ++yi) {
1567 for (
int xi = 0; xi < _x_size; ++xi) {
1568 LPoint3f uv((PN_float32(xi) + 0.5) * uv_scale[0],
1569 (PN_float32(yi) + 0.5) * uv_scale[1],
1587 float xr,
float yr,
float exponent) {
1588 int minx = max((
int)cceil(xc - xr), 0);
1589 int maxx = min((
int)cfloor(xc + xr), _x_size - 1);
1590 int miny = max((
int)cceil(yc - yr), 0);
1591 int maxy = min((
int)cfloor(yc + yr), _y_size - 1);
1594 for (
int yi = miny; yi <= maxy; ++yi) {
1595 for (
int xi = minx; xi <= maxx; ++xi) {
1596 float xd = ((float)xi - xc) / xr;
1597 float yd = ((float)yi - yc) / yr;
1598 float r2 = xd * xd + yd * yd;
1602 PN_float32 t = (PN_float32)cpow(1.0f - csqrt(r2), exponent);
1604 PN_float32 *f = &_table[(yi * _x_size + xi) * _num_channels];
1605 for (
int ci = 0; ci < _num_channels; ++ci) {
1606 f[ci] += delta[ci] * t;
1627 min_point.set(0.0f, 0.0f, 0.0f);
1628 max_point.set(0.0f, 0.0f, 0.0f);
1630 bool found_any =
false;
1631 for (
int yi = 0; yi < _y_size; ++yi) {
1632 for (
int xi = 0; xi < _x_size; ++xi) {
1643 min_point.set(min(min_point[0], point[0]),
1644 min(min_point[1], point[1]),
1645 min(min_point[2], point[2]));
1646 max_point.set(max(max_point[0], point[0]),
1647 max(max_point[1], point[1]),
1648 max(max_point[2], point[2]));
1676 compute_planar_bounds(const
LPoint2f ¢er, PN_float32 point_dist, PN_float32 sample_radius,
bool points_only)
const {
1678 compute_sample_point(p0, center[0] + point_dist, center[1] - point_dist, sample_radius);
1679 compute_sample_point(p1, center[0] + point_dist, center[1] + point_dist, sample_radius);
1680 compute_sample_point(p2, center[0] - point_dist, center[1] + point_dist, sample_radius);
1681 compute_sample_point(p3, center[0] - point_dist, center[1] - point_dist, sample_radius);
1685 normal[0] = p0[1] * p1[2] - p0[2] * p1[1];
1686 normal[1] = p0[2] * p1[0] - p0[0] * p1[2];
1687 normal[2] = p0[0] * p1[1] - p0[1] * p1[0];
1689 normal[0] += p1[1] * p2[2] - p1[2] * p2[1];
1690 normal[1] += p1[2] * p2[0] - p1[0] * p2[2];
1691 normal[2] += p1[0] * p2[1] - p1[1] * p2[0];
1693 normal[0] += p2[1] * p3[2] - p2[2] * p3[1];
1694 normal[1] += p2[2] * p3[0] - p2[0] * p3[2];
1695 normal[2] += p2[0] * p3[1] - p2[1] * p3[0];
1697 normal[0] += p3[1] * p0[2] - p3[2] * p0[1];
1698 normal[1] += p3[2] * p0[0] - p3[0] * p0[2];
1699 normal[2] += p3[0] * p0[1] - p3[1] * p0[0];
1704 LPoint3f pcenter = ((p0 + p1 + p2 + p3) * 0.25);
1709 look_at(rotate, normal, up);
1719 PN_float32 min_x, min_y, min_z, max_x, max_y, max_z;
1720 bool got_point =
false;
1728 for (
int i = 0; i < 4; ++i) {
1739 min_x = min(min_x, point[0]);
1740 min_y = min(min_y, point[1]);
1741 min_z = min(min_z, point[2]);
1742 max_x = max(max_x, point[0]);
1743 max_y = max(max_y, point[1]);
1744 max_z = max(max_z, point[2]);
1749 for (
int yi = 0; yi < _y_size; ++yi) {
1750 for (
int xi = 0; xi < _x_size; ++xi) {
1751 if (!has_point(xi, yi)) {
1755 LPoint3f point = get_point(xi, yi) * rinv;
1765 min_x = min(min_x, point[0]);
1766 min_y = min(min_y, point[1]);
1767 min_z = min(min_z, point[2]);
1768 max_x = max(max_x, point[0]);
1769 max_y = max(max_y, point[1]);
1770 max_z = max(max_z, point[2]);
1780 CoordinateSystem cs = get_default_coordinate_system();
1815 nassertr(
false, NULL);
1820 bounds->xform(LCAST(PN_stdfloat, rotate));
1837 PN_float32 x, PN_float32 y, PN_float32 sample_radius)
const {
1840 PN_float32 xr = sample_radius * _x_size;
1841 PN_float32 yr = sample_radius * _y_size;
1843 switch (_num_channels) {
1847 box_filter_region(result1, x - xr, y - yr, x + xr, y + yr);
1848 result.set(result1, 0.0, 0.0);
1855 box_filter_region(result2, x - xr, y - yr, x + xr, y + yr);
1856 result.set(result2[0], result2[1], 0.0);
1861 box_filter_region(result, x - xr, y - yr, x + xr, y + yr);
1867 box_filter_region(result4, x - xr, y - yr, x + xr, y + yr);
1868 result.set(result4[0], result4[1], result4[2]);
1890 int xfrom,
int yfrom,
int x_size,
int y_size) {
1891 int xmin, ymin, xmax, ymax;
1892 setup_sub_image(copy, xto, yto, xfrom, yfrom, x_size, y_size,
1893 xmin, ymin, xmax, ymax);
1896 switch (_num_channels) {
1899 for (y = ymin; y < ymax; y++) {
1900 for (x = xmin; x < xmax; x++) {
1901 if (copy.
has_point(x - xmin + xfrom, y - ymin + yfrom)) {
1911 for (y = ymin; y < ymax; y++) {
1912 for (x = xmin; x < xmax; x++) {
1913 if (copy.
has_point(x - xmin + xfrom, y - ymin + yfrom)) {
1923 for (y = ymin; y < ymax; y++) {
1924 for (x = xmin; x < xmax; x++) {
1925 if (copy.
has_point(x - xmin + xfrom, y - ymin + yfrom)) {
1935 for (y = ymin; y < ymax; y++) {
1936 for (x = xmin; x < xmax; x++) {
1937 if (copy.
has_point(x - xmin + xfrom, y - ymin + yfrom)) {
1956 int xfrom,
int yfrom,
int x_size,
int y_size,
1957 float pixel_scale) {
1958 int xmin, ymin, xmax, ymax;
1959 setup_sub_image(copy, xto, yto, xfrom, yfrom, x_size, y_size,
1960 xmin, ymin, xmax, ymax);
1963 switch (_num_channels) {
1966 for (y = ymin; y < ymax; y++) {
1967 for (x = xmin; x < xmax; x++) {
1978 for (y = ymin; y < ymax; y++) {
1979 for (x = xmin; x < xmax; x++) {
1990 for (y = ymin; y < ymax; y++) {
1991 for (x = xmin; x < xmax; x++) {
2002 for (y = ymin; y < ymax; y++) {
2003 for (x = xmin; x < xmax; x++) {
2023 int xfrom,
int yfrom,
int x_size,
int y_size,
2024 float pixel_scale) {
2025 int xmin, ymin, xmax, ymax;
2026 setup_sub_image(copy, xto, yto, xfrom, yfrom, x_size, y_size,
2027 xmin, ymin, xmax, ymax);
2030 switch (_num_channels) {
2033 for (y = ymin; y < ymax; y++) {
2034 for (x = xmin; x < xmax; x++) {
2045 for (y = ymin; y < ymax; y++) {
2046 for (x = xmin; x < xmax; x++) {
2057 for (y = ymin; y < ymax; y++) {
2058 for (x = xmin; x < xmax; x++) {
2069 for (y = ymin; y < ymax; y++) {
2070 for (x = xmin; x < xmax; x++) {
2091 int xfrom,
int yfrom,
int x_size,
int y_size,
2092 float pixel_scale) {
2093 int xmin, ymin, xmax, ymax;
2094 setup_sub_image(copy, xto, yto, xfrom, yfrom, x_size, y_size,
2095 xmin, ymin, xmax, ymax);
2098 switch (_num_channels) {
2101 for (y = ymin; y < ymax; y++) {
2102 for (x = xmin; x < xmax; x++) {
2113 for (y = ymin; y < ymax; y++) {
2114 for (x = xmin; x < xmax; x++) {
2128 for (y = ymin; y < ymax; y++) {
2129 for (x = xmin; x < xmax; x++) {
2144 for (y = ymin; y < ymax; y++) {
2145 for (x = xmin; x < xmax; x++) {
2169 nassertv(is_valid());
2171 switch (_num_channels) {
2174 for (
int y = 0; y < _y_size; ++y) {
2175 for (
int x = 0; x < _x_size; ++x) {
2188 for (
int y = 0; y < _y_size; ++y) {
2189 for (
int x = 0; x < _x_size; ++x) {
2201 for (
int y = 0; y < _y_size; ++y) {
2202 for (
int x = 0; x < _x_size; ++x) {
2214 for (
int y = 0; y < _y_size; ++y) {
2215 for (
int x = 0; x < _x_size; ++x) {
2233 output(ostream &out)
const {
2234 out <<
"floating-point image: " << _x_size <<
" by " << _y_size <<
" pixels, "
2235 << _num_channels <<
" channels.";
2248 box_filter_region(PN_float32 &result,
2249 PN_float32 x0, PN_float32 y0, PN_float32 x1, PN_float32 y1)
const {
2251 PN_float32 coverage = 0.0;
2253 if (x1 < x0 || y1 < y0) {
2256 nassertv(y0 >= 0.0 && y1 >= 0.0);
2260 box_filter_line(result, coverage, x0, y, x1, (PN_float32)(y+1)-y0);
2262 int y_last = (int)y1;
2265 while (y < y_last) {
2267 box_filter_line(result, coverage, x0, y, x1, 1.0);
2272 PN_float32 y_contrib = y1 - (PN_float32)y_last;
2273 if (y_contrib > 0.0001) {
2274 box_filter_line(result, coverage, x0, y, x1, y_contrib);
2278 if (coverage != 0.0) {
2293 box_filter_region(
LPoint2f &result,
2294 PN_float32 x0, PN_float32 y0, PN_float32 x1, PN_float32 y1)
const {
2296 PN_float32 coverage = 0.0;
2298 if (x1 < x0 || y1 < y0) {
2301 nassertv(y0 >= 0.0 && y1 >= 0.0);
2305 box_filter_line(result, coverage, x0, y, x1, (PN_float32)(y+1)-y0);
2307 int y_last = (int)y1;
2310 while (y < y_last) {
2312 box_filter_line(result, coverage, x0, y, x1, 1.0);
2317 PN_float32 y_contrib = y1 - (PN_float32)y_last;
2318 if (y_contrib > 0.0001) {
2319 box_filter_line(result, coverage, x0, y, x1, y_contrib);
2323 if (coverage != 0.0) {
2338 box_filter_region(
LPoint3f &result,
2339 PN_float32 x0, PN_float32 y0, PN_float32 x1, PN_float32 y1)
const {
2341 PN_float32 coverage = 0.0;
2343 if (x1 < x0 || y1 < y0) {
2346 nassertv(y0 >= 0.0 && y1 >= 0.0);
2350 box_filter_line(result, coverage, x0, y, x1, (PN_float32)(y+1)-y0);
2352 int y_last = (int)y1;
2355 while (y < y_last) {
2357 box_filter_line(result, coverage, x0, y, x1, 1.0);
2362 PN_float32 y_contrib = y1 - (PN_float32)y_last;
2363 if (y_contrib > 0.0001) {
2364 box_filter_line(result, coverage, x0, y, x1, y_contrib);
2368 if (coverage != 0.0) {
2383 box_filter_region(
LPoint4f &result,
2384 PN_float32 x0, PN_float32 y0, PN_float32 x1, PN_float32 y1)
const {
2386 PN_float32 coverage = 0.0;
2388 if (x1 < x0 || y1 < y0) {
2391 nassertv(y0 >= 0.0 && y1 >= 0.0);
2395 box_filter_line(result, coverage, x0, y, x1, (PN_float32)(y+1)-y0);
2397 int y_last = (int)y1;
2400 while (y < y_last) {
2402 box_filter_line(result, coverage, x0, y, x1, 1.0);
2407 PN_float32 y_contrib = y1 - (PN_float32)y_last;
2408 if (y_contrib > 0.0001) {
2409 box_filter_line(result, coverage, x0, y, x1, y_contrib);
2413 if (coverage != 0.0) {
2424 box_filter_line(PN_float32 &result, PN_float32 &coverage,
2425 PN_float32 x0,
int y, PN_float32 x1, PN_float32 y_contrib)
const {
2428 box_filter_point(result, coverage, x, y, (PN_float32)(x+1)-x0, y_contrib);
2430 int x_last = (int)x1;
2433 while (x < x_last) {
2435 box_filter_point(result, coverage, x, y, 1.0, y_contrib);
2440 PN_float32 x_contrib = x1 - (PN_float32)x_last;
2441 if (x_contrib > 0.0001) {
2442 box_filter_point(result, coverage, x, y, x_contrib, y_contrib);
2453 box_filter_line(
LPoint2f &result, PN_float32 &coverage,
2454 PN_float32 x0,
int y, PN_float32 x1, PN_float32 y_contrib)
const {
2457 box_filter_point(result, coverage, x, y, (PN_float32)(x+1)-x0, y_contrib);
2459 int x_last = (int)x1;
2462 while (x < x_last) {
2464 box_filter_point(result, coverage, x, y, 1.0, y_contrib);
2469 PN_float32 x_contrib = x1 - (PN_float32)x_last;
2470 if (x_contrib > 0.0001) {
2471 box_filter_point(result, coverage, x, y, x_contrib, y_contrib);
2482 box_filter_line(
LPoint3f &result, PN_float32 &coverage,
2483 PN_float32 x0,
int y, PN_float32 x1, PN_float32 y_contrib)
const {
2486 box_filter_point(result, coverage, x, y, (PN_float32)(x+1)-x0, y_contrib);
2488 int x_last = (int)x1;
2491 while (x < x_last) {
2493 box_filter_point(result, coverage, x, y, 1.0, y_contrib);
2498 PN_float32 x_contrib = x1 - (PN_float32)x_last;
2499 if (x_contrib > 0.0001) {
2500 box_filter_point(result, coverage, x, y, x_contrib, y_contrib);
2511 box_filter_line(
LPoint4f &result, PN_float32 &coverage,
2512 PN_float32 x0,
int y, PN_float32 x1, PN_float32 y_contrib)
const {
2515 box_filter_point(result, coverage, x, y, (PN_float32)(x+1)-x0, y_contrib);
2517 int x_last = (int)x1;
2520 while (x < x_last) {
2522 box_filter_point(result, coverage, x, y, 1.0, y_contrib);
2527 PN_float32 x_contrib = x1 - (PN_float32)x_last;
2528 if (x_contrib > 0.0001) {
2529 box_filter_point(result, coverage, x, y, x_contrib, y_contrib);
2540 box_filter_point(PN_float32 &result, PN_float32 &coverage,
2541 int x,
int y, PN_float32 x_contrib, PN_float32 y_contrib)
const {
2547 PN_float32 contrib = x_contrib * y_contrib;
2548 result += point * contrib;
2549 coverage += contrib;
2558 box_filter_point(
LPoint2f &result, PN_float32 &coverage,
2559 int x,
int y, PN_float32 x_contrib, PN_float32 y_contrib)
const {
2565 PN_float32 contrib = x_contrib * y_contrib;
2566 result += point * contrib;
2567 coverage += contrib;
2576 box_filter_point(
LPoint3f &result, PN_float32 &coverage,
2577 int x,
int y, PN_float32 x_contrib, PN_float32 y_contrib)
const {
2583 PN_float32 contrib = x_contrib * y_contrib;
2584 result += point * contrib;
2585 coverage += contrib;
2594 box_filter_point(
LPoint4f &result, PN_float32 &coverage,
2595 int x,
int y, PN_float32 x_contrib, PN_float32 y_contrib)
const {
2601 PN_float32 contrib = x_contrib * y_contrib;
2602 result += point * contrib;
2603 coverage += contrib;
2614 fill_mini_grid(MiniGridCell *mini_grid,
int x_size,
int y_size,
2615 int xi,
int yi,
int dist,
int sxi,
int syi)
const {
2616 if (xi < 0 || xi >= x_size || yi < 0 || yi >= y_size) {
2621 int gi = yi * x_size + xi;
2622 if (mini_grid[gi]._dist == -1 || mini_grid[gi]._dist > dist) {
2624 mini_grid[gi]._dist = dist;
2625 mini_grid[gi]._sxi = sxi;
2626 mini_grid[gi]._syi = syi;
2627 fill_mini_grid(mini_grid, x_size, y_size, xi + 1, yi, dist + 1, sxi, syi);
2628 fill_mini_grid(mini_grid, x_size, y_size, xi - 1, yi, dist + 1, sxi, syi);
2629 fill_mini_grid(mini_grid, x_size, y_size, xi, yi + 1, dist + 1, sxi, syi);
2630 fill_mini_grid(mini_grid, x_size, y_size, xi, yi - 1, dist + 1, sxi, syi);
2641 has_point_noop(
const PfmFile *
self,
int x,
int y) {
2642 if ((x >= 0 && x < self->_x_size) &&
2643 (y >= 0 && y < self->_y_size)) {
2656 has_point_1(
const PfmFile *
self,
int x,
int y) {
2657 if ((x >= 0 && x < self->_x_size) &&
2658 (y >= 0 && y < self->_y_size)) {
2659 return self->_table[(y *
self->_x_size + x)] != self->_no_data_value[0];
2671 has_point_2(
const PfmFile *
self,
int x,
int y) {
2672 if ((x >= 0 && x < self->_x_size) &&
2673 (y >= 0 && y < self->_y_size)) {
2674 return *(
LPoint2f *)&self->_table[(y * self->_x_size + x) * 2] != *(
LPoint2f *)&self->_no_data_value;
2686 has_point_3(
const PfmFile *
self,
int x,
int y) {
2687 if ((x >= 0 && x < self->_x_size) &&
2688 (y >= 0 && y < self->_y_size)) {
2689 return *(
LPoint3f *)&self->_table[(y * self->_x_size + x) * 3] != *(
LPoint3f *)&self->_no_data_value;
2701 has_point_4(
const PfmFile *
self,
int x,
int y) {
2702 if ((x >= 0 && x < self->_x_size) &&
2703 (y >= 0 && y < self->_y_size)) {
2704 return *(
LPoint4f *)&self->_table[(y * self->_x_size + x) * 4] != *(
LPoint4f *)&self->_no_data_value;
2716 has_point_threshold_1(
const PfmFile *
self,
int x,
int y) {
2717 if ((x >= 0 && x < self->_x_size) &&
2718 (y >= 0 && y < self->_y_size)) {
2719 const float *table = &
self->_table[(y *
self->_x_size + x)];
2720 return table[0] >=
self->_no_data_value[0];
2732 has_point_threshold_2(
const PfmFile *
self,
int x,
int y) {
2733 if ((x >= 0 && x < self->_x_size) &&
2734 (y >= 0 && y < self->_y_size)) {
2735 const float *table = &
self->_table[(y *
self->_x_size + x) * 2];
2736 return (table[0] >= self->_no_data_value[0] ||
2737 table[1] >= self->_no_data_value[1]);
2749 has_point_threshold_3(
const PfmFile *
self,
int x,
int y) {
2750 if ((x >= 0 && x < self->_x_size) &&
2751 (y >= 0 && y < self->_y_size)) {
2752 const float *table = &
self->_table[(y *
self->_x_size + x) * 3];
2753 return (table[0] >= self->_no_data_value[0] ||
2754 table[1] >= self->_no_data_value[1] ||
2755 table[2] >= self->_no_data_value[2]);
2767 has_point_threshold_4(
const PfmFile *
self,
int x,
int y) {
2768 if ((x >= 0 && x < self->_x_size) &&
2769 (y >= 0 && y < self->_y_size)) {
2770 const float *table = &
self->_table[(y *
self->_x_size + x) * 4];
2771 return (table[0] >= self->_no_data_value[0] ||
2772 table[1] >= self->_no_data_value[1] ||
2773 table[2] >= self->_no_data_value[2] ||
2774 table[3] >= self->_no_data_value[3]);
2787 has_point_chan4(
const PfmFile *
self,
int x,
int y) {
2788 if ((x >= 0 && x < self->_x_size) &&
2789 (y >= 0 && y < self->_y_size)) {
2790 return self->_table[(y *
self->_x_size + x) * 4 + 3] >= 0.0;
2803 has_point_nan_1(
const PfmFile *
self,
int x,
int y) {
2804 if ((x >= 0 && x < self->_x_size) &&
2805 (y >= 0 && y < self->_y_size)) {
2806 return !cnan(self->_table[(y * self->_x_size + x) * self->_num_channels]);
2819 has_point_nan_2(
const PfmFile *
self,
int x,
int y) {
2820 if ((x >= 0 && x < self->_x_size) &&
2821 (y >= 0 && y < self->_y_size)) {
2822 return !((
LVecBase2f *)&self->_table[(y * self->_x_size + x) *
self->_num_channels])->is_nan();
2835 has_point_nan_3(
const PfmFile *
self,
int x,
int y) {
2836 if ((x >= 0 && x < self->_x_size) &&
2837 (y >= 0 && y < self->_y_size)) {
2838 return !((
LVecBase3f *)&self->_table[(y * self->_x_size + x) *
self->_num_channels])->is_nan();
2851 has_point_nan_4(
const PfmFile *
self,
int x,
int y) {
2852 if ((x >= 0 && x < self->_x_size) &&
2853 (y >= 0 && y < self->_y_size)) {
2854 return !((
LVecBase4f *)&self->_table[(y * self->_x_size + x) *
self->_num_channels])->is_nan();
bool calc_min_max(LVecBase3f &min_points, LVecBase3f &max_points) const
Calculates the minimum and maximum x, y, and z depth component values, representing the bounding box ...
bool is_row_empty(int y, int x_begin, int x_end) const
Returns true if all of the points on row y, in the range [x_begin, x_end), are the no_data value...
void forward_distort(const PfmFile &dist, PN_float32 scale_factor=1.0)
Applies the distortion indicated in the supplied dist map to the current map.
This is the base class for all three-component vectors and points.
void copy_header_from(const PNMImageHeader &header)
Initializes all the data in the header (x_size, y_size, num_channels, etc.) to the same values indica...
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...
bool calc_average_point(LPoint3f &result, PN_float32 x, PN_float32 y, PN_float32 radius) const
Computes the unweighted average point of all points within the box centered at (x, y) with the indicated Manhattan-distance radius.
PN_float32 get_point1(int x, int y) const
Returns the 1-component point value at the indicated point.
void xform_point_general_in_place(LVecBase3f &v) const
The matrix transforms a 3-component point (including translation component), as a fully general opera...
void fill_channel_masked(int channel, PN_float32 value)
Fills the indicated channel with all of the same value, but only where the table already has a data p...
LColorf get_xel_a(int x, int y) const
Returns the RGBA color at the indicated pixel.
void mult_sub_image(const PfmFile ©, int xto, int yto, int xfrom=0, int yfrom=0, int x_size=-1, int y_size=-1, float pixel_scale=1.0)
Behaves like copy_sub_image(), except the copy pixels are multiplied to the pixels of the destination...
void fill_channel(int channel, PN_float32 value)
Fills the indicated channel with all of the same value, leaving the other channels unchanged...
bool store(PNMImage &pnmimage) const
Copies the data to the indicated PNMImage, converting to RGB values.
void set_point4(int x, int y, const LVecBase4f &point)
Replaces the 4-component point value at the indicated point.
A hierarchy of directories and files that appears to be one continuous file system, even though the files may originate from several different sources that may not be related to the actual OS's file system.
virtual bool write_pfm(const PfmFile &pfm)
Writes floating-point data from the indicated PfmFile.
static const LPoint3f & zero()
Returns a zero-length point.
bool read(const Filename &filename, PNMFileType *type=NULL, bool report_unknown_type=true)
Reads the indicated image filename.
virtual bool is_floating_point()
Returns true if this PNMFileType represents a floating-point image type, false if it is a normal...
PN_float32 get_channel(int x, int y, int c) const
Returns the cth channel of the point value at the indicated point.
void fill_nan()
Fills the table with all NaN.
float get_gray(int x, int y) const
Returns the gray component color at the indicated pixel.
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
bool calc_bilinear_point(LPoint3f &result, PN_float32 x, PN_float32 y) const
Computes the weighted average of the four nearest points to the floating-point index (x...
void fill_channel_masked_nan(int channel)
Fills the indicated channel with NaN, but only where the table already has a data point...
void fill_channel_nan(int channel)
Fills the indicated channel with NaN, leaving the other channels unchanged.
xel * get_array()
Directly access the underlying PNMImage array.
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
bool is_nan() const
Returns true if any component of the vector is not-a-number, false otherwise.
void set_point2(int x, int y, const LVecBase2f &point)
Replaces the 2-component point value at the indicated point.
static const LVecBase3f & zero()
Returns a zero-length vector.
The abstract base class for a file or directory within the VirtualFileSystem.
float get_alpha(int x, int y) const
Returns the alpha component color at the indicated pixel.
static void close_read_file(istream *stream)
Closes a file opened by a previous call to open_read_file().
void set_point3(int x, int y, const LVecBase3f &point)
Replaces the 3-component point value at the indicated point.
virtual bool supports_floating_point()
Returns true if this PNMFileType can accept a floating-point image type, false if it can only accept ...
static const LPoint4f & zero()
Returns a zero-length point.
virtual bool read_pfm(PfmFile &pfm)
Reads floating-point data directly into the indicated PfmFile.
void resize(int new_x_size, int new_y_size)
Applies a simple filter to resample the pfm file in-place to the indicated size.
This is our own Panda specialization on the default STL vector.
bool is_column_empty(int x, int y_begin, int y_end) const
Returns true if all of the points on column x, from [y_begin, y_end), are the no_data value...
LPoint4f & modify_point4(int x, int y)
Returns a modifiable 4-component point value at the indicated point.
bool read(const Filename &fullpath)
Reads the PFM data from the indicated file, returning true on success, false on failure.
void set_point1(int x, int y, PN_float32 point)
Replaces the 1-component point value at the indicated point.
bool write(const Filename &fullpath)
Writes the PFM data to the indicated file, returning true on success, false on failure.
void gaussian_filter_from(float radius, const PfmFile ©)
Makes a resized copy of the indicated image into this one using the indicated filter.
void merge(const PfmFile &other)
Wherever there is missing data in this PfmFile (that is, wherever has_point() returns false)...
void copy_sub_image(const PfmFile ©, int xto, int yto, int xfrom=0, int yfrom=0, int x_size=-1, int y_size=-1)
Copies a rectangular area of another image into a rectangular area of this image. ...
void copy_channel_masked(int to_channel, const PfmFile &other, int from_channel)
Copies just the specified channel values from the indicated PfmFile, but only where the other file ha...
void apply_crop(int x_begin, int x_end, int y_begin, int y_end)
Reduces the PFM file to the cells in the rectangle bounded by (x_begin, x_end, y_begin, y_end), where the _end cells are not included.
LPoint3f & modify_point3(int x, int y)
Returns a modifiable 3-component point value at the indicated point.
const LPoint2f & get_point2(int x, int y) const
Returns the 2-component point value at the indicated point.
The name of a file, such as a texture file or an Egg file.
Defines a pfm file, a 2-d table of floating-point numbers, either 3-component or 1-component, or with a special extension, 2- or 4-component.
void reverse_rows()
Performs an in-place reversal of the row (y) data.
This is a 4-by-4 transform matrix.
void set_gray(int x, int y, float gray)
Sets the gray component color at the indicated pixel.
bool has_point(int x, int y) const
Returns true if there is a valid point at x, y.
void compute_sample_point(LPoint3f &result, PN_float32 x, PN_float32 y, PN_float32 sample_radius) const
Computes the average of all the point within sample_radius (manhattan distance) and the indicated poi...
void box_filter_from(float radius, const PfmFile ©)
Makes a resized copy of the indicated image into this one using the indicated filter.
void clear_to_texcoords(int x_size, int y_size)
Replaces this PfmFile with a new PfmFile of size x_size x y_size x 3, containing the x y 0 values in ...
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
bool is_valid() const
Returns true if the PNMReader can be used to read data, false if something is wrong.
bool invert_from(const LMatrix4f &other)
Computes the inverse of the other matrix, and stores the result in this matrix.
void set_xel_a(int x, int y, const LColorf &value)
Changes the RGBA color at the indicated pixel.
void reverse_distort(const PfmFile &dist, PN_float32 scale_factor=1.0)
Applies the distortion indicated in the supplied dist map to the current map.
const LPoint3f & get_point3(int x, int y) const
Returns the 3-component point value at the indicated point.
This is the base class for all two-component vectors and points.
void fill(PN_float32 value)
Fills the table with all of the same value.
void operator*=(float multiplier)
Multiplies every point value in the image by a constant floating-point multiplier value...
void set_point(int x, int y, const LVecBase3f &point)
Replaces the 3-component point value at the indicated point.
const LPoint4f & get_point4(int x, int y) const
Returns the 4-component point value at the indicated point.
static const LPoint2f & zero()
Returns a zero-length point.
void flip(bool flip_x, bool flip_y, bool transpose)
Reverses, transposes, and/or rotates the table in-place according to the specified parameters...
xelval * get_alpha_array()
Directly access the underlying PNMImage array of alpha values.
void quick_filter_from(const PfmFile ©)
Resizes from the given image, with a fixed radius of 0.5.
This is an abstract base class that defines the interface for reading image files of various types...
This is an abstract base class that defines the interface for writing image files of various types...
PointerTo< VirtualFile > get_file(const Filename &filename, bool status_only=false) const
Looks up the file by the indicated name in the file system.
void set_channel(int x, int y, int c, PN_float32 value)
Replaces the cth channel of the point value at the indicated point.
bool load(const PNMImage &pnmimage)
Fills the PfmFile with the data from the indicated PNMImage, converted to floating-point values...
int pull_spot(const LPoint4f &delta, float xc, float yc, float xr, float yr, float exponent)
Applies delta * t to the point values within radius (xr, yr) distance of (xc, yc).
This is the base class for all three-component vectors and points.
virtual int write_data(xel *array, xelval *alpha)
Writes out an entire image all at once, including the header, based on the image data stored in the g...
bool calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point) const
Calculates the minimum and maximum vertices of all points within the table.
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.
void xform(const LMatrix4f &transform)
Applies the indicated transform matrix to all points in-place.
void divide_sub_image(const PfmFile ©, int xto, int yto, int xfrom=0, int yfrom=0, int x_size=-1, int y_size=-1, float pixel_scale=1.0)
Behaves like copy_sub_image(), except the copy pixels are divided into the pixels of the destination...
This is a four-component point in space.
LPoint3f & modify_point(int x, int y)
Returns a modifiable 3-component point value at the indicated point.
void copy_channel(int to_channel, const PfmFile &other, int from_channel)
Copies just the specified channel values from the indicated PfmFile (which could be same as this PfmF...
void clear_no_data_value()
Removes the special value that means "no data" when it appears in the pfm file.
void set_row(int row, const LVecBase4f &v)
Replaces the indicated row of the matrix.
LRGBColorf get_xel(int x, int y) const
Returns the RGB color at the indicated pixel.
const LPoint3f & get_point(int x, int y) const
Returns the 3-component point value at the indicated point.
This is a two-component point in space.
bool open_write(ofstream &stream, bool truncate=true) const
Opens the indicated ifstream for writing the file, if possible.
void set_no_data_threshold(const LPoint4f &no_data_value)
Sets the special threshold value.
void fill_no_data_value()
Fills the table with the current no_data value, so that the table is empty.
bool store_mask(PNMImage &pnmimage) const
Stores 1 or 0 values into the indicated PNMImage, according to has_point() for each pixel...
LPoint2f & modify_point2(int x, int y)
Returns a modifiable 2-component point value at the indicated point.
bool normalize()
Normalizes the vector in place.
void add_sub_image(const PfmFile ©, int xto, int yto, int xfrom=0, int yfrom=0, int x_size=-1, int y_size=-1, float pixel_scale=1.0)
Behaves like copy_sub_image(), except the copy pixels are added to the pixels of the destination...
void set_xel(int x, int y, const LRGBColorf &value)
Changes the RGB color at the indicated pixel.
void set_no_data_nan(int num_channels)
Sets the no_data_nan flag.
void clear()
Eliminates all data in the file.
This defines a bounding convex hexahedron.
bool calc_autocrop(int &x_begin, int &x_end, int &y_begin, int &y_end) const
Computes the minimum range of x and y across the PFM file that include all points.
void set_no_data_value(const LPoint4f &no_data_value)
Sets the special value that means "no data" when it appears in the pfm file.