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);