diff --git a/panda/src/pnmimage/config_pnmimage.cxx b/panda/src/pnmimage/config_pnmimage.cxx index f35b808f0d..ebc1de8e20 100644 --- a/panda/src/pnmimage/config_pnmimage.cxx +++ b/panda/src/pnmimage/config_pnmimage.cxx @@ -37,7 +37,7 @@ ConfigVariableBool pfm_reverse_dimensions "on input. Does not affect output, which is always written width height.")); ConfigVariableBool pfm_resize_quick -("pfm-resize-quick", false, +("pfm-resize-quick", true, PRC_DESC("Specify true to implement PfmFile::resize() with a \"quick\" filter, " "but only when the pfm is being downsampled (to a smaller size). " "This just controls the behavior of resize(); you can " @@ -47,13 +47,13 @@ ConfigVariableBool pfm_resize_gaussian ("pfm-resize-gaussian", true, PRC_DESC("Specify true to implement PfmFile::resize() with a higher-quality " "Gaussian filter, or false to implement it with a faster box " - "filter. If pfm-resize-quick is also true, then only takes effect " + "filter. If pfm-resize-quick is also true, this only takes effect " "when the pfm is being upsampled. This just controls the behavior " "of resize(); you can always call box_filter() or gaussian_filter() " "explicitly.")); ConfigVariableDouble pfm_resize_radius -("pfm-resize-radius", 0.5, +("pfm-resize-radius", 1.0, PRC_DESC("Specify the default filter radius for PfmFile::resize(). " "This just controls the behavior of resize(); you can " "always call box_filter() or gaussian_filter() explicitly with " diff --git a/panda/src/pnmimage/pnm-image-filter.cxx b/panda/src/pnmimage/pnm-image-filter.cxx index 31a01c6c4e..ae687a8b16 100644 --- a/panda/src/pnmimage/pnm-image-filter.cxx +++ b/panda/src/pnmimage/pnm-image-filter.cxx @@ -111,25 +111,28 @@ filter_row(StoreType dest[], int dest_len, double scale, // == dest_len / source_len const WorkType filter[], double filter_width) { - // If we are expanding the row (scale>1.0), we need to look at a fractional - // granularity. Hence, we scale our filter index by scale. If we are - // compressing (scale<1.0), we don't need to fiddle with the filter index, so - // we leave it at one. - double iscale = max(scale, 1.0); + // If we are expanding the row (scale > 1.0), we need to look at a + // fractional granularity. Hence, we scale our filter index by + // scale. If we are compressing (scale < 1.0), we don't need to + // fiddle with the filter index, so we leave it at one. - // Similarly, if we are expanding the row, we want to start the new row at - // the far left edge of the original pixel, not in the center. So we will - // have a non-zero offset. - int offset = (int)cfloor(iscale*0.5); + double iscale; + if (scale < 1.0) { + iscale = 1.0; + filter_width /= scale; + } else { + iscale = scale; + } for (int dest_x = 0; dest_x < dest_len; dest_x++) { - double center = (dest_x - offset) / scale; + // The additional offset of 0.5 keeps the pixel centered. + double center = (dest_x + 0.5) / scale - 0.5; // left and right are the starting and ending ranges of the radius of // interest of the filter function. We need to apply the filter to each // value in this range. int left = max((int)cfloor(center - filter_width), 0); - int right = min((int)cceil(center + filter_width), source_len-1); + int right = min((int)cceil(center + filter_width), source_len - 1); // right_center is the point just to the right of the center. This // allows us to flip the sign of the offset when we cross the center point. @@ -144,13 +147,13 @@ filter_row(StoreType dest[], int dest_len, // of center--so we don't have to incur the overhead of calling fabs() // each time through the loop. for (source_x = left; source_x < right_center; source_x++) { - index = (int)(iscale * (center - source_x)); + index = (int)(iscale * (center - source_x) + 0.5); net_value += filter[index] * source[source_x]; net_weight += filter[index]; } for (; source_x <= right; source_x++) { - index = (int)(iscale * (source_x - center)); + index = (int)(iscale * (source_x - center) + 0.5); net_value += filter[index] * source[source_x]; net_weight += filter[index]; } @@ -172,26 +175,28 @@ filter_sparse_row(StoreType dest[], StoreType dest_weight[], int dest_len, double scale, // == dest_len / source_len const WorkType filter[], double filter_width) { - // If we are expanding the row (scale>1.0), we need to look at a fractional - // granularity. Hence, we scale our filter index by scale. If we are - // compressing (scale<1.0), we don't need to fiddle with the filter index, so - // we leave it at one. - double iscale = max(scale, 1.0); + // If we are expanding the row (scale > 1.0), we need to look at a + // fractional granularity. Hence, we scale our filter index by + // scale. If we are compressing (scale < 1.0), we don't need to + // fiddle with the filter index, so we leave it at one. - // Similarly, if we are expanding the row, we want to start the new row at - // the far left edge of the original pixel, not in the center. So we will - // have a non-zero offset. - int offset = (int)cfloor(iscale*0.5); + double iscale; + if (scale < 1.0) { + iscale = 1.0; + filter_width /= scale; + } else { + iscale = scale; + } for (int dest_x = 0; dest_x < dest_len; dest_x++) { // The additional offset of 0.5 keeps the pixel centered. - double center = (dest_x - offset + 0.5) / scale; + double center = (dest_x + 0.5) / scale - 0.5; // left and right are the starting and ending ranges of the radius of // interest of the filter function. We need to apply the filter to each // value in this range. int left = max((int)cfloor(center - filter_width), 0); - int right = min((int)cceil(center + filter_width), source_len-1); + int right = min((int)cceil(center + filter_width), source_len - 1); // right_center is the point just to the right of the center. This // allows us to flip the sign of the offset when we cross the center point. @@ -206,13 +211,13 @@ filter_sparse_row(StoreType dest[], StoreType dest_weight[], int dest_len, // of center--so we don't have to incur the overhead of calling fabs() // each time through the loop. for (source_x = left; source_x < right_center; source_x++) { - index = (int)(iscale * (center - source_x)); + index = (int)(iscale * (center - source_x) + 0.5); net_value += filter[index] * source[source_x] * source_weight[source_x]; net_weight += filter[index] * source_weight[source_x]; } for (; source_x <= right; source_x++) { - index = (int)(iscale * (source_x - center)); + index = (int)(iscale * (source_x - center) + 0.5); net_value += filter[index] * source[source_x] * source_weight[source_x]; net_weight += filter[index] * source_weight[source_x]; } @@ -258,7 +263,7 @@ box_filter_impl(double scale, double width, fscale = scale; } filter_width = width; - int actual_width = (int)cceil((filter_width + 1) * fscale); + int actual_width = (int)cceil((filter_width + 1) * fscale) + 1; filter = (WorkType *)PANDA_MALLOC_ARRAY(actual_width * sizeof(WorkType));