77 typedef float WorkType;
78 typedef float StoreType;
79 static const WorkType source_max = 1.0f;
80 static const WorkType filter_max = 1.0f;
109 filter_row(StoreType dest[],
int dest_len,
110 const StoreType source[],
int source_len,
112 const WorkType filter[],
113 float filter_width) {
122 filter_width /= scale;
127 for (
int dest_x = 0; dest_x < dest_len; dest_x++) {
129 float center = (dest_x + 0.5f) / scale - 0.5f;
134 int left = max((
int)cfloor(center - filter_width), 0);
135 int right = min((
int)cceil(center + filter_width), source_len - 1);
139 int right_center = (int)cceil(center);
141 WorkType net_weight = 0;
142 WorkType net_value = 0;
149 for (source_x = left; source_x < right_center; source_x++) {
150 index = (int)(iscale * (center - source_x) + 0.5f);
151 net_value += filter[index] * source[source_x];
152 net_weight += filter[index];
155 for (; source_x <= right; source_x++) {
156 index = (int)(iscale * (source_x - center) + 0.5f);
157 net_value += filter[index] * source[source_x];
158 net_weight += filter[index];
161 if (net_weight > 0) {
162 dest[dest_x] = (StoreType)(net_value / net_weight);
173 filter_sparse_row(StoreType dest[], StoreType dest_weight[],
int dest_len,
174 const StoreType source[],
const StoreType source_weight[],
int source_len,
176 const WorkType filter[],
177 float filter_width) {
186 filter_width /= scale;
191 for (
int dest_x = 0; dest_x < dest_len; dest_x++) {
193 float center = (dest_x + 0.5f) / scale - 0.5f;
198 int left = max((
int)cfloor(center - filter_width), 0);
199 int right = min((
int)cceil(center + filter_width), source_len - 1);
203 int right_center = (int)cceil(center);
205 WorkType net_weight = 0;
206 WorkType net_value = 0;
213 for (source_x = left; source_x < right_center; source_x++) {
214 index = (int)(iscale * (center - source_x) + 0.5f);
215 net_value += filter[index] * source[source_x] * source_weight[source_x];
216 net_weight += filter[index] * source_weight[source_x];
219 for (; source_x <= right; source_x++) {
220 index = (int)(iscale * (source_x - center) + 0.5f);
221 net_value += filter[index] * source[source_x] * source_weight[source_x];
222 net_weight += filter[index] * source_weight[source_x];
225 if (net_weight > 0) {
226 dest[dest_x] = (StoreType)(net_value / net_weight);
230 dest_weight[dest_x] = (StoreType)net_weight;
246 typedef void FilterFunction(
float scale,
float width,
247 WorkType *&filter,
float &filter_width);
250 box_filter_impl(
float scale,
float width,
251 WorkType *&filter,
float &filter_width) {
257 fscale = 1.0 / scale;
265 filter_width = width;
266 int actual_width = (int)cceil((filter_width + 1) * fscale) + 1;
268 filter = (WorkType *)PANDA_MALLOC_ARRAY(actual_width *
sizeof(WorkType));
270 for (
int i = 0; i < actual_width; i++) {
271 filter[i] = (i <= filter_width * fscale) ? filter_max : 0;
276 gaussian_filter_impl(
float scale,
float width,
277 WorkType *&filter,
float &filter_width) {
283 fscale = 1.0 / scale;
292 float sigma = width/2;
293 filter_width = 3.0 * sigma;
294 int actual_width = (int)cceil((filter_width + 1) * fscale);
302 filter = (WorkType *)PANDA_MALLOC_ARRAY(actual_width *
sizeof(WorkType));
303 float div = 2 * sigma * sigma;
305 for (
int i = 0; i < actual_width; i++) {
306 float x = i / fscale;
307 filter[i] = (WorkType)(filter_max * exp(-x*x / div));
339 #define FUNCTION_NAME filter_red_xy
340 #define IMAGETYPE PNMImage
341 #define ASIZE get_x_size
342 #define BSIZE get_y_size
343 #define GETVAL(a, b, channel) get_red(a, b)
344 #define SETVAL(a, b, channel, v) set_red(a, b, v)
353 #define FUNCTION_NAME filter_green_xy
354 #define IMAGETYPE PNMImage
355 #define ASIZE get_x_size
356 #define BSIZE get_y_size
357 #define GETVAL(a, b, channel) get_green(a, b)
358 #define SETVAL(a, b, channel, v) set_green(a, b, v)
367 #define FUNCTION_NAME filter_blue_xy
368 #define IMAGETYPE PNMImage
369 #define ASIZE get_x_size
370 #define BSIZE get_y_size
371 #define GETVAL(a, b, channel) get_blue(a, b)
372 #define SETVAL(a, b, channel, v) set_blue(a, b, v)
381 #define FUNCTION_NAME filter_gray_xy
382 #define IMAGETYPE PNMImage
383 #define ASIZE get_x_size
384 #define BSIZE get_y_size
385 #define GETVAL(a, b, channel) get_bright(a, b)
386 #define SETVAL(a, b, channel, v) set_xel(a, b, v)
395 #define FUNCTION_NAME filter_alpha_xy
396 #define IMAGETYPE PNMImage
397 #define ASIZE get_x_size
398 #define BSIZE get_y_size
399 #define GETVAL(a, b, channel) get_alpha(a, b)
400 #define SETVAL(a, b, channel, v) set_alpha(a, b, v)
412 #define FUNCTION_NAME filter_red_yx
413 #define IMAGETYPE PNMImage
414 #define ASIZE get_y_size
415 #define BSIZE get_x_size
416 #define GETVAL(a, b, channel) get_red(b, a)
417 #define SETVAL(a, b, channel, v) set_red(b, a, v)
426 #define FUNCTION_NAME filter_green_yx
427 #define IMAGETYPE PNMImage
428 #define ASIZE get_y_size
429 #define BSIZE get_x_size
430 #define GETVAL(a, b, channel) get_green(b, a)
431 #define SETVAL(a, b, channel, v) set_green(b, a, v)
440 #define FUNCTION_NAME filter_blue_yx
441 #define IMAGETYPE PNMImage
442 #define ASIZE get_y_size
443 #define BSIZE get_x_size
444 #define GETVAL(a, b, channel) get_blue(b, a)
445 #define SETVAL(a, b, channel, v) set_blue(b, a, v)
454 #define FUNCTION_NAME filter_gray_yx
455 #define IMAGETYPE PNMImage
456 #define ASIZE get_y_size
457 #define BSIZE get_x_size
458 #define GETVAL(a, b, channel) get_bright(b, a)
459 #define SETVAL(a, b, channel, v) set_xel(b, a, v)
468 #define FUNCTION_NAME filter_alpha_yx
469 #define IMAGETYPE PNMImage
470 #define ASIZE get_y_size
471 #define BSIZE get_x_size
472 #define GETVAL(a, b, channel) get_alpha(b, a)
473 #define SETVAL(a, b, channel, v) set_alpha(b, a, v)
487 float width, FilterFunction *make_filter) {
499 filter_gray_xy(dest, source, width, make_filter, 0);
501 filter_red_xy(dest, source, width, make_filter, 0);
502 filter_green_xy(dest, source, width, make_filter, 0);
503 filter_blue_xy(dest, source, width, make_filter, 0);
507 filter_alpha_xy(dest, source, width, make_filter, 0);
512 filter_gray_yx(dest, source, width, make_filter, 0);
514 filter_red_yx(dest, source, width, make_filter, 0);
515 filter_green_yx(dest, source, width, make_filter, 0);
516 filter_blue_yx(dest, source, width, make_filter, 0);
520 filter_alpha_yx(dest, source, width, make_filter, 0);
533 filter_image(*
this, copy, width, &box_filter_impl);
544 filter_image(*
this, copy, width, &gaussian_filter_impl);
551 #define FUNCTION_NAME filter_pfm_xy
552 #define IMAGETYPE PfmFile
553 #define ASIZE get_x_size
554 #define BSIZE get_y_size
555 #define GETVAL(a, b, channel) get_channel(a, b, channel)
556 #define SETVAL(a, b, channel, v) set_channel(a, b, channel, v)
565 #define FUNCTION_NAME filter_pfm_yx
566 #define IMAGETYPE PfmFile
567 #define ASIZE get_y_size
568 #define BSIZE get_x_size
569 #define GETVAL(a, b, channel) get_channel(b, a, channel)
570 #define SETVAL(a, b, channel, v) set_channel(b, a, channel, v)
580 #define FUNCTION_NAME filter_pfm_sparse_xy
581 #define IMAGETYPE PfmFile
582 #define ASIZE get_x_size
583 #define BSIZE get_y_size
584 #define HASVAL(a, b) has_point(a, b)
585 #define GETVAL(a, b, channel) get_channel(a, b, channel)
586 #define SETVAL(a, b, channel, v) set_channel(a, b, channel, v)
596 #define FUNCTION_NAME filter_pfm_sparse_yx
597 #define IMAGETYPE PfmFile
598 #define ASIZE get_y_size
599 #define BSIZE get_x_size
600 #define HASVAL(a, b) has_point(b, a)
601 #define GETVAL(a, b, channel) get_channel(b, a, channel)
602 #define SETVAL(a, b, channel, v) set_channel(b, a, channel, v)
617 float width, FilterFunction *make_filter) {
623 for (
int ci = 0; ci < num_channels; ++ci) {
624 filter_pfm_sparse_xy(dest, source, width, make_filter, ci);
628 for (
int ci = 0; ci < num_channels; ++ci) {
629 filter_pfm_sparse_yx(dest, source, width, make_filter, ci);
635 for (
int ci = 0; ci < num_channels; ++ci) {
636 filter_pfm_xy(dest, source, width, make_filter, ci);
640 for (
int ci = 0; ci < num_channels; ++ci) {
641 filter_pfm_yx(dest, source, width, make_filter, ci);
655 filter_image(*
this, copy, width, &box_filter_impl);
666 filter_image(*
this, copy, width, &gaussian_filter_impl);
673 int x,
int y,
float x_contrib,
float y_contrib,
674 LColorf &color,
float &pixel_count) {
676 float contrib = x_contrib * y_contrib;
678 pixel_count += contrib;
682 box_filter_line(
const PNMImage &image,
683 float x0,
int y,
float x1,
float y_contrib,
684 LColorf &color,
float &pixel_count) {
687 box_filter_xel(image, x, y, (
float)(x+1)-x0, y_contrib,
690 int x_last = (int)x1;
695 box_filter_xel(image, x, y, 1.0f, y_contrib,
701 float x_contrib = x1 - (float)x_last;
702 if (x_contrib > 0.0001f && x < image.
get_x_size()) {
703 box_filter_xel(image, x, y, x_contrib, y_contrib,
710 box_filter_region(
const PNMImage &image,
711 float x0,
float y0,
float x1,
float y1) {
712 LColorf color = LColorf::zero();
713 float pixel_count = 0.0f;
715 assert(y0 >= 0 && y1 >= 0);
719 box_filter_line(image, x0, y, x1, (
float)(y+1)-y0,
722 int y_last = (int)y1;
727 box_filter_line(image, x0, y, x1, 1.0f,
733 float y_contrib = y1 - (float)y_last;
734 if (y_contrib > 0.0001f && y < image.
get_y_size()) {
735 box_filter_line(image, x0, y, x1, y_contrib,
741 color /= pixel_count;
761 int to_xoff = xborder / 2;
762 int to_yoff = yborder / 2;
764 float from_x0, from_x1, from_y0, from_y1;
767 float x_scale = (float)from_xs / (
float)to_xs;
768 float y_scale = (float)from_ys / (
float)to_ys;
772 from_y0 = max(0, -to_yoff) * y_scale;
773 for (to_y = max(0, -to_yoff);
776 from_y1 = (to_y+1) * y_scale;
778 from_x0 = max(0, -to_xoff) * x_scale;
779 for (to_x = max(0, -to_xoff);
782 from_x1 = (to_x+1) * x_scale;
786 color = box_filter_region(from,
787 from_x0, from_y0, from_x1, from_y1);
789 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...
void gaussian_filter_from(float radius, const PNMImage ©)
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.
void quick_filter_from(const PNMImage ©, int xborder=0, int yborder=0)
Resizes from the given image, with a fixed radius of 0.5.
LColorf get_xel_a(int x, int y) const
Returns the RGBA color at the indicated pixel.
void box_filter_from(float radius, const PNMImage ©)
Makes a resized copy of the indicated image into this one using the indicated filter.
Defines a pfm file, a 2-d table of floating-point numbers, either 3-component or 1-component,...
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 PfmFile ©)
Makes a resized copy of the indicated image into this one using the indicated filter.
void box_filter_from(float radius, const PfmFile ©)
Makes a resized copy of the indicated image into this one using the indicated filter.
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.