فهرست منبع

Fix the calculation of the input image shift when using subpixel regions. Includes some more tests which had incorrect results before and now work fine.

Jorge Rodriguez 10 سال پیش
والد
کامیت
cf6f69cdc9
2فایلهای تغییر یافته به همراه49 افزوده شده و 11 حذف شده
  1. 10 10
      stb_image_resize.h
  2. 39 1
      tests/resample_test.cpp

+ 10 - 10
stb_image_resize.h

@@ -1004,31 +1004,31 @@ stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max)
 }
 
 // What input pixels contribute to this output pixel?
-static void stbir__calculate_sample_range_upsample(int n, float out_filter_radius, float scale_ratio, float out_shift, int* in_first_pixel, int* in_last_pixel, float* in_center_of_out)
+static void stbir__calculate_sample_range_upsample(int n, float out_filter_radius, float scale_ratio, float in_shift, int* in_first_pixel, int* in_last_pixel, float* in_center_of_out)
 {
     float out_pixel_center = (float)n + 0.5f;
     float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius;
     float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius;
 
-    float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) / scale_ratio;
-    float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) / scale_ratio;
+    float in_pixel_influence_lowerbound = out_pixel_influence_lowerbound / scale_ratio + in_shift;
+    float in_pixel_influence_upperbound = out_pixel_influence_upperbound / scale_ratio + in_shift;
 
-    *in_center_of_out = (out_pixel_center + out_shift) / scale_ratio;
+    *in_center_of_out = out_pixel_center / scale_ratio + in_shift;
     *in_first_pixel = (int)(floor(in_pixel_influence_lowerbound + 0.5));
     *in_last_pixel = (int)(floor(in_pixel_influence_upperbound - 0.5));
 }
 
 // What output pixels does this input pixel contribute to?
-static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radius, float scale_ratio, float out_shift, int* out_first_pixel, int* out_last_pixel, float* out_center_of_in)
+static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radius, float scale_ratio, float in_shift, int* out_first_pixel, int* out_last_pixel, float* out_center_of_in)
 {
     float in_pixel_center = (float)n + 0.5f;
     float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius;
     float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius;
 
-    float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale_ratio - out_shift;
-    float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale_ratio - out_shift;
+    float out_pixel_influence_lowerbound = (in_pixel_influence_lowerbound - in_shift) * scale_ratio;
+    float out_pixel_influence_upperbound = (in_pixel_influence_upperbound - in_shift) * scale_ratio;
 
-    *out_center_of_in = in_pixel_center * scale_ratio - out_shift;
+    *out_center_of_in = (in_pixel_center - in_shift) * scale_ratio;
     *out_first_pixel = (int)(floor(out_pixel_influence_lowerbound + 0.5));
     *out_last_pixel = (int)(floor(out_pixel_influence_upperbound - 0.5));
 }
@@ -2229,8 +2229,8 @@ static void stbir__calculate_transform(stbir__info *info, float s0, float t0, fl
         info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0);
         info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0);
 
-        info->horizontal_shift = s0 * info->input_w / (s1 - s0);
-        info->vertical_shift = t0 * info->input_h / (t1 - t0);
+        info->horizontal_shift = s0 * info->input_w;
+        info->vertical_shift = t0 * info->input_h;
     }
 }
 

+ 39 - 1
tests/resample_test.cpp

@@ -1,4 +1,5 @@
-#include <malloc.h>
+#include <stdlib.h>
+#include <stdio.h>
 
 #if defined(_WIN32) && _MSC_VER > 1200
 #define STBIR_ASSERT(x) \
@@ -356,6 +357,30 @@ void test_subpixel(const char* file, float width_percent, float height_percent,
 	free(output_data);
 }
 
+void test_subpixel_really(const char* file, float width_percent, float height_percent, float s0, float t0, float s1, float t1)
+{
+	int w, h, n;
+	unsigned char* input_data = stbi_load(file, &w, &h, &n, 0);
+
+	if (input_data == NULL)
+		return;
+
+	int new_w = (int)(w * width_percent);
+	int new_h = (int)(h * height_percent);
+
+	unsigned char* output_data = (unsigned char*)malloc(new_w * new_h * n * sizeof(unsigned char));
+
+	stbir_resize_region(input_data, w, h, 0, output_data, new_w, new_h, 0, STBIR_TYPE_UINT8, n, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_BOX, STBIR_FILTER_CATMULLROM, STBIR_COLORSPACE_SRGB, &g_context, s0, t0, s1, t1);
+
+	stbi_image_free(input_data);
+
+	char output[200];
+	sprintf(output, "test-output/subpixel-really-%d-%d-%f-%f-%f-%f-%s", new_w, new_h, s0, t0, s1, t1, file);
+	stbi_write_png(output, new_w, new_h, n, output_data, 0);
+
+	free(output_data);
+}
+
 unsigned int* pixel(unsigned int* buffer, int x, int y, int c, int w, int n)
 {
 	return &buffer[y*w*n + x*n + c];
@@ -880,6 +905,19 @@ void test_suite(int argc, char **argv)
 	stbir_resize(image88, 8, 8, 0, output88, 16, 4, 0, STBIR_TYPE_UINT8, 1, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_BOX, STBIR_FILTER_CATMULLROM, STBIR_COLORSPACE_SRGB, &g_context);
 	stbir_resize(image88, 8, 8, 0, output88, 16, 4, 0, STBIR_TYPE_UINT8, 1, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_CATMULLROM, STBIR_FILTER_BOX, STBIR_COLORSPACE_SRGB, &g_context);
 
+	int res = 10;
+	for (int i = 0; i < res; i++)
+	{
+		float t = (float)i/res / 2;
+		test_subpixel_really(barbara, 0.5f, 0.5f, t, t, t+0.5f, t+0.5f);
+	}
+
+	for (int i = 0; i < res; i++)
+	{
+		float t = (float)i/res / 2;
+		test_subpixel_really(barbara, 2, 2, t, t, t+0.5f, t+0.5f);
+	}
+
 	for (i = 0; i < 10; i++)
 		test_subpixel(barbara, 0.5f, 0.5f, (float)i / 10, 1);