35 #include "pandabase.h" 76 typedef float WorkType;
77 typedef float StoreType;
78 static const WorkType source_max = 1.0f;
79 static const WorkType filter_max = 1.0f;
108 filter_row(StoreType dest[],
int dest_len,
109 const StoreType source[],
int source_len,
111 const WorkType filter[],
112 float filter_width) {
121 filter_width /= scale;
126 for (
int dest_x = 0; dest_x < dest_len; dest_x++) {
128 float center = (dest_x + 0.5f) / scale - 0.5f;
133 int left = max((
int)cfloor(center - filter_width), 0);
134 int right = min((
int)cceil(center + filter_width), source_len - 1);
138 int right_center = (int)cceil(center);
140 WorkType net_weight = 0;
141 WorkType net_value = 0;
148 for (source_x = left; source_x < right_center; source_x++) {
149 index = (int)(iscale * (center - source_x) + 0.5f);
150 net_value += filter[index] * source[source_x];
151 net_weight += filter[index];
154 for (; source_x <= right; source_x++) {
155 index = (int)(iscale * (source_x - center) + 0.5f);
156 net_value += filter[index] * source[source_x];
157 net_weight += filter[index];
160 if (net_weight > 0) {
161 dest[dest_x] = (StoreType)(net_value / net_weight);
172 filter_sparse_row(StoreType dest[], StoreType dest_weight[],
int dest_len,
173 const StoreType source[],
const StoreType source_weight[],
int source_len,
175 const WorkType filter[],
176 float filter_width) {
185 filter_width /= scale;
190 for (
int dest_x = 0; dest_x < dest_len; dest_x++) {
192 float center = (dest_x + 0.5f) / scale - 0.5f;
197 int left = max((
int)cfloor(center - filter_width), 0);
198 int right = min((
int)cceil(center + filter_width), source_len - 1);
202 int right_center = (int)cceil(center);
204 WorkType net_weight = 0;
205 WorkType net_value = 0;
212 for (source_x = left; source_x < right_center; source_x++) {
213 index = (int)(iscale * (center - source_x) + 0.5f);
214 net_value += filter[index] * source[source_x] * source_weight[source_x];
215 net_weight += filter[index] * source_weight[source_x];
218 for (; source_x <= right; source_x++) {
219 index = (int)(iscale * (source_x - center) + 0.5f);
220 net_value += filter[index] * source[source_x] * source_weight[source_x];
221 net_weight += filter[index] * source_weight[source_x];
224 if (net_weight > 0) {
225 dest[dest_x] = (StoreType)(net_value / net_weight);
229 dest_weight[dest_x] = (StoreType)net_weight;
245 typedef void FilterFunction(
float scale,
float width,
246 WorkType *&filter,
float &filter_width);
249 box_filter_impl(
float scale,
float width,
250 WorkType *&filter,
float &filter_width) {
256 fscale = 1.0 / scale;
264 filter_width = width;
265 int actual_width = (int)cceil((filter_width + 1) * fscale) + 1;
267 filter = (WorkType *)PANDA_MALLOC_ARRAY(actual_width *
sizeof(WorkType));
269 for (
int i = 0; i < actual_width; i++) {
270 filter[i] = (i <= filter_width * fscale) ? filter_max : 0;
275 gaussian_filter_impl(
float scale,
float width,
276 WorkType *&filter,
float &filter_width) {
282 fscale = 1.0 / scale;
291 float sigma = width/2;
292 filter_width = 3.0 * sigma;
293 int actual_width = (int)cceil((filter_width + 1) * fscale);
301 filter = (WorkType *)PANDA_MALLOC_ARRAY(actual_width *
sizeof(WorkType));
302 float div = 2 * sigma * sigma;
304 for (
int i = 0; i < actual_width; i++) {
305 float x = i / fscale;
306 filter[i] = (WorkType)(filter_max * exp(-x*x / div));
338 #define FUNCTION_NAME filter_red_xy 339 #define IMAGETYPE PNMImage 340 #define ASIZE get_x_size 341 #define BSIZE get_y_size 342 #define GETVAL(a, b, channel) get_red(a, b) 343 #define SETVAL(a, b, channel, v) set_red(a, b, v) 344 #include "pnm-image-filter-core.cxx" 352 #define FUNCTION_NAME filter_green_xy 353 #define IMAGETYPE PNMImage 354 #define ASIZE get_x_size 355 #define BSIZE get_y_size 356 #define GETVAL(a, b, channel) get_green(a, b) 357 #define SETVAL(a, b, channel, v) set_green(a, b, v) 358 #include "pnm-image-filter-core.cxx" 366 #define FUNCTION_NAME filter_blue_xy 367 #define IMAGETYPE PNMImage 368 #define ASIZE get_x_size 369 #define BSIZE get_y_size 370 #define GETVAL(a, b, channel) get_blue(a, b) 371 #define SETVAL(a, b, channel, v) set_blue(a, b, v) 372 #include "pnm-image-filter-core.cxx" 380 #define FUNCTION_NAME filter_gray_xy 381 #define IMAGETYPE PNMImage 382 #define ASIZE get_x_size 383 #define BSIZE get_y_size 384 #define GETVAL(a, b, channel) get_bright(a, b) 385 #define SETVAL(a, b, channel, v) set_xel(a, b, v) 386 #include "pnm-image-filter-core.cxx" 394 #define FUNCTION_NAME filter_alpha_xy 395 #define IMAGETYPE PNMImage 396 #define ASIZE get_x_size 397 #define BSIZE get_y_size 398 #define GETVAL(a, b, channel) get_alpha(a, b) 399 #define SETVAL(a, b, channel, v) set_alpha(a, b, v) 400 #include "pnm-image-filter-core.cxx" 411 #define FUNCTION_NAME filter_red_yx 412 #define IMAGETYPE PNMImage 413 #define ASIZE get_y_size 414 #define BSIZE get_x_size 415 #define GETVAL(a, b, channel) get_red(b, a) 416 #define SETVAL(a, b, channel, v) set_red(b, a, v) 417 #include "pnm-image-filter-core.cxx" 425 #define FUNCTION_NAME filter_green_yx 426 #define IMAGETYPE PNMImage 427 #define ASIZE get_y_size 428 #define BSIZE get_x_size 429 #define GETVAL(a, b, channel) get_green(b, a) 430 #define SETVAL(a, b, channel, v) set_green(b, a, v) 431 #include "pnm-image-filter-core.cxx" 439 #define FUNCTION_NAME filter_blue_yx 440 #define IMAGETYPE PNMImage 441 #define ASIZE get_y_size 442 #define BSIZE get_x_size 443 #define GETVAL(a, b, channel) get_blue(b, a) 444 #define SETVAL(a, b, channel, v) set_blue(b, a, v) 445 #include "pnm-image-filter-core.cxx" 453 #define FUNCTION_NAME filter_gray_yx 454 #define IMAGETYPE PNMImage 455 #define ASIZE get_y_size 456 #define BSIZE get_x_size 457 #define GETVAL(a, b, channel) get_bright(b, a) 458 #define SETVAL(a, b, channel, v) set_xel(b, a, v) 459 #include "pnm-image-filter-core.cxx" 467 #define FUNCTION_NAME filter_alpha_yx 468 #define IMAGETYPE PNMImage 469 #define ASIZE get_y_size 470 #define BSIZE get_x_size 471 #define GETVAL(a, b, channel) get_alpha(b, a) 472 #define SETVAL(a, b, channel, v) set_alpha(b, a, v) 473 #include "pnm-image-filter-core.cxx" 486 float width, FilterFunction *make_filter) {
498 filter_gray_xy(dest, source, width, make_filter, 0);
500 filter_red_xy(dest, source, width, make_filter, 0);
501 filter_green_xy(dest, source, width, make_filter, 0);
502 filter_blue_xy(dest, source, width, make_filter, 0);
506 filter_alpha_xy(dest, source, width, make_filter, 0);
511 filter_gray_yx(dest, source, width, make_filter, 0);
513 filter_red_yx(dest, source, width, make_filter, 0);
514 filter_green_yx(dest, source, width, make_filter, 0);
515 filter_blue_yx(dest, source, width, make_filter, 0);
519 filter_alpha_yx(dest, source, width, make_filter, 0);
535 filter_image(*
this, copy, width, &box_filter_impl);
549 filter_image(*
this, copy, width, &gaussian_filter_impl);
557 #define FUNCTION_NAME filter_pfm_xy 558 #define IMAGETYPE PfmFile 559 #define ASIZE get_x_size 560 #define BSIZE get_y_size 561 #define GETVAL(a, b, channel) get_channel(a, b, channel) 562 #define SETVAL(a, b, channel, v) set_channel(a, b, channel, v) 563 #include "pnm-image-filter-core.cxx" 571 #define FUNCTION_NAME filter_pfm_yx 572 #define IMAGETYPE PfmFile 573 #define ASIZE get_y_size 574 #define BSIZE get_x_size 575 #define GETVAL(a, b, channel) get_channel(b, a, channel) 576 #define SETVAL(a, b, channel, v) set_channel(b, a, channel, v) 577 #include "pnm-image-filter-core.cxx" 586 #define FUNCTION_NAME filter_pfm_sparse_xy 587 #define IMAGETYPE PfmFile 588 #define ASIZE get_x_size 589 #define BSIZE get_y_size 590 #define HASVAL(a, b) has_point(a, b) 591 #define GETVAL(a, b, channel) get_channel(a, b, channel) 592 #define SETVAL(a, b, channel, v) set_channel(a, b, channel, v) 593 #include "pnm-image-filter-sparse-core.cxx" 602 #define FUNCTION_NAME filter_pfm_sparse_yx 603 #define IMAGETYPE PfmFile 604 #define ASIZE get_y_size 605 #define BSIZE get_x_size 606 #define HASVAL(a, b) has_point(b, a) 607 #define GETVAL(a, b, channel) get_channel(b, a, channel) 608 #define SETVAL(a, b, channel, v) set_channel(b, a, channel, v) 609 #include "pnm-image-filter-sparse-core.cxx" 623 float width, FilterFunction *make_filter) {
629 for (
int ci = 0; ci < num_channels; ++ci) {
630 filter_pfm_sparse_xy(dest, source, width, make_filter, ci);
634 for (
int ci = 0; ci < num_channels; ++ci) {
635 filter_pfm_sparse_yx(dest, source, width, make_filter, ci);
641 for (
int ci = 0; ci < num_channels; ++ci) {
642 filter_pfm_xy(dest, source, width, make_filter, ci);
646 for (
int ci = 0; ci < num_channels; ++ci) {
647 filter_pfm_yx(dest, source, width, make_filter, ci);
664 filter_image(*
this, copy, width, &box_filter_impl);
678 filter_image(*
this, copy, width, &gaussian_filter_impl);
687 int x,
int y,
float x_contrib,
float y_contrib,
688 LColorf &color,
float &pixel_count) {
690 float contrib = x_contrib * y_contrib;
692 pixel_count += contrib;
696 box_filter_line(
const PNMImage &image,
697 float x0,
int y,
float x1,
float y_contrib,
698 LColorf &color,
float &pixel_count) {
701 box_filter_xel(image, x, y, (
float)(x+1)-x0, y_contrib,
704 int x_last = (int)x1;
709 box_filter_xel(image, x, y, 1.0f, y_contrib,
715 float x_contrib = x1 - (float)x_last;
716 if (x_contrib > 0.0001f && x < image.
get_x_size()) {
717 box_filter_xel(image, x, y, x_contrib, y_contrib,
724 box_filter_region(
const PNMImage &image,
725 float x0,
float y0,
float x1,
float y1) {
727 float pixel_count = 0.0f;
729 assert(y0 >= 0 && y1 >= 0);
733 box_filter_line(image, x0, y, x1, (
float)(y+1)-y0,
736 int y_last = (int)y1;
741 box_filter_line(image, x0, y, x1, 1.0f,
747 float y_contrib = y1 - (float)y_last;
748 if (y_contrib > 0.0001f && y < image.
get_y_size()) {
749 box_filter_line(image, x0, y, x1, y_contrib,
755 color /= pixel_count;
779 int to_xoff = xborder / 2;
780 int to_yoff = yborder / 2;
782 float from_x0, from_x1, from_y0, from_y1;
785 float x_scale = (float)from_xs / (
float)to_xs;
786 float y_scale = (float)from_ys / (
float)to_ys;
790 from_y0 = max(0, -to_yoff) * y_scale;
791 for (to_y = max(0, -to_yoff);
794 from_y1 = (to_y+1) * y_scale;
796 from_x0 = max(0, -to_xoff) * x_scale;
797 for (to_x = max(0, -to_xoff);
800 from_x1 = (to_x+1) * x_scale;
804 color = box_filter_region(from,
805 from_x0, from_y0, from_x1, from_y1);
807 set_xel_a(to_xoff + to_x, to_yoff + to_y, color);
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
void quick_filter_from(const PNMImage ©, int xborder=0, int yborder=0)
Resizes from the given image, with a fixed radius of 0.5.
void gaussian_filter_from(float radius, const PfmFile ©)
Makes a resized copy of the indicated image into this one using the indicated filter.
LColorf get_xel_a(int x, int y) const
Returns the RGBA color at the indicated pixel.
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 box_filter_from(float radius, const PfmFile ©)
Makes a resized copy of the indicated image into this one using the indicated filter.
void set_xel_a(int x, int y, const LColorf &value)
Changes the RGBA color at the indicated pixel.
bool has_no_data_value() const
Returns whether a "no data" value has been established by set_no_data_value().
void gaussian_filter_from(float radius, const PNMImage ©)
Makes a resized copy of the indicated image into this one using the indicated filter.
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.
static const LVecBase4f & zero()
Returns a zero-length vector.