Browse Source

fix off-by-one on gaussian_filter and box_filter

David Rose 12 years ago
parent
commit
c7daa00c5b

+ 13 - 11
panda/src/pnmimage/config_pnmimage.cxx

@@ -36,22 +36,24 @@ ConfigVariableBool pfm_reverse_dimensions
           "backwards, in the form height width instead of width height, "
           "backwards, in the form height width instead of width height, "
           "on input.  Does not affect output, which is always written width height."));
           "on input.  Does not affect output, which is always written width height."));
 
 
+ConfigVariableBool pfm_resize_quick
+("pfm-resize-quick", false,
+ 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 "
+          "always call quick_filter() explicitly."));
+
 ConfigVariableBool pfm_resize_gaussian
 ConfigVariableBool pfm_resize_gaussian
-("pfm-resize-gaussian", false,
+("pfm-resize-gaussian", true,
  PRC_DESC("Specify true to implement PfmFile::resize() with a higher-quality "
  PRC_DESC("Specify true to implement PfmFile::resize() with a higher-quality "
           "Gaussian filter, or false to implement it with a faster box "
           "Gaussian filter, or false to implement it with a faster box "
-          "filter.  This just controls the behavior of resize(); you can "
-          "always call box_filter() or gaussian_filter() explicitly."));
-
-ConfigVariableBool pfm_resize_quick
-("pfm-resize-quick", true,
- PRC_DESC("If pfm-resize-gaussian is false, set this true to allow the "
-          "so-called \"quick\" filter when the pfm is being downscaled.  This "
-          "is even faster than the normal box filter.  In some cases it "
-          "may also be more precise, though it may be more aliased."));
+          "filter.  If pfm-resize-quick is also true, then 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
 ConfigVariableDouble pfm_resize_radius
-("pfm-resize-radius", 1.0,
+("pfm-resize-radius", 0.5,
  PRC_DESC("Specify the default filter radius for PfmFile::resize().  "
  PRC_DESC("Specify the default filter radius for PfmFile::resize().  "
           "This just controls the behavior of resize(); you can "
           "This just controls the behavior of resize(); you can "
           "always call box_filter() or gaussian_filter() explicitly with "
           "always call box_filter() or gaussian_filter() explicitly with "

+ 8 - 7
panda/src/pnmimage/pfmFile.cxx

@@ -989,15 +989,16 @@ resize(int new_x_size, int new_y_size) {
     result.fill(_no_data_value);
     result.fill(_no_data_value);
   }
   }
 
 
-  if (pfm_resize_gaussian) {
-    result.gaussian_filter_from(pfm_resize_radius, *this);
+  if (pfm_resize_quick && new_x_size <= _x_size && new_y_size <= _y_size) {
+    // If we're downscaling, we can use quick_filter, which is faster.
+    result.quick_filter_from(*this);
+    
   } else {
   } else {
-    if (pfm_resize_quick && new_x_size <= _x_size && new_y_size <= _y_size) {
-      // If we're downscaling, we can use quick_filter, which is faster.
-      result.quick_filter_from(*this);
-      
+    // Otherwise, we should use box_filter() or gaussian_filter, which
+    // are more general.
+    if (pfm_resize_gaussian) {
+      result.gaussian_filter_from(pfm_resize_radius, *this);
     } else {
     } else {
-      // Otherwise, we should use box_filter(), which is more general.
       result.box_filter_from(pfm_resize_radius, *this);
       result.box_filter_from(pfm_resize_radius, *this);
     }
     }
   }
   }

+ 2 - 1
panda/src/pnmimage/pnm-image-filter.cxx

@@ -184,7 +184,8 @@ filter_sparse_row(StoreType dest[], StoreType dest_weight[], int dest_len,
   int offset = (int)cfloor(iscale*0.5);
   int offset = (int)cfloor(iscale*0.5);
 
 
   for (int dest_x = 0; dest_x < dest_len; dest_x++) {
   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 - offset + 0.5) / scale;
 
 
     // left and right are the starting and ending ranges of the radius of
     // 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
     // interest of the filter function.  We need to apply the filter to each