4 #if defined(_WIN32) && _MSC_VER > 1200
5 #define STBIR_ASSERT(x) \
11 #define STBIR_ASSERT(x) assert(x)
14 #define STBIR_MALLOC stbir_malloc
15 #define STBIR_FREE stbir_free
22 memory
= malloc(size
);
34 void* stbir_malloc(size_t size
, void* context
)
39 stbir_context
* real_context
= (stbir_context
*)context
;
40 if (size
> real_context
->size
)
43 return real_context
->memory
;
46 void stbir_free(void* memory
, void* context
)
53 void stbir_progress(float p
)
56 STBIR_ASSERT(p
>= 0 && p
<= 1);
59 #define STBIR_PROGRESS_REPORT stbir_progress
61 #define STB_IMAGE_RESIZE_IMPLEMENTATION
62 #define STB_IMAGE_RESIZE_STATIC
63 #include "stb_image_resize.h"
65 #define STB_IMAGE_WRITE_IMPLEMENTATION
66 #include "stb_image_write.h"
68 #define STB_IMAGE_IMPLEMENTATION
69 #include "stb_image.h"
72 #include <sys/timeb.h>
78 static size_t g_aiMT
[MT_SIZE
];
79 static size_t g_iMTI
= 0;
81 // Mersenne Twister implementation from Wikipedia.
82 // Avoiding use of the system rand() to be sure that our tests generate the same test data on any system.
83 void mtsrand(size_t iSeed
)
86 for (size_t i
= 1; i
< MT_SIZE
; i
++)
88 size_t inner1
= g_aiMT
[i
- 1];
89 size_t inner2
= (g_aiMT
[i
- 1] >> 30);
90 size_t inner
= inner1
^ inner2
;
91 g_aiMT
[i
] = (0x6c078965 * inner
) + i
;
101 for (size_t i
= 0; i
< MT_SIZE
; i
++)
103 size_t y
= (0x80000000 & (g_aiMT
[i
])) + (0x7fffffff & (g_aiMT
[(i
+ 1) % MT_SIZE
]));
104 g_aiMT
[i
] = g_aiMT
[(i
+ 397) % MT_SIZE
] ^ (y
>> 1);
106 g_aiMT
[i
] = g_aiMT
[i
] ^ 0x9908b0df;
110 size_t y
= g_aiMT
[g_iMTI
];
112 y
= y
^ ((y
<< 7) & (0x9d2c5680));
113 y
= y
^ ((y
<< 15) & (0xefc60000));
116 g_iMTI
= (g_iMTI
+ 1) % MT_SIZE
;
122 inline float mtfrand()
124 const int ninenine
= 999999;
125 return (float)(mtrand() % ninenine
)/ninenine
;
128 static void resizer(int argc
, char **argv
)
130 unsigned char* input_pixels
;
131 unsigned char* output_pixels
;
135 input_pixels
= stbi_load(argv
[1], &w
, &h
, &n
, 0);
138 output_pixels
= (unsigned char*) malloc(out_w
*out_h
*n
);
139 //stbir_resize_uint8_srgb(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, n, -1,0);
140 stbir_resize_uint8(input_pixels
, w
, h
, 0, output_pixels
, out_w
, out_h
, 0, n
);
141 stbi_write_png("output.png", out_w
, out_h
, n
, output_pixels
, 0);
145 static void performance(int argc
, char **argv
)
147 unsigned char* input_pixels
;
148 unsigned char* output_pixels
;
151 int out_w
, out_h
, srgb
=1;
152 input_pixels
= stbi_load(argv
[1], &w
, &h
, &n
, 0);
154 out_w
= w
/4; out_h
= h
/4; count
=100; // 1
156 out_w
= w
*2; out_h
= h
/4; count
=20; // 2 // note this is structured pessimily, would be much faster to downsample vertically first
158 out_w
= w
/4; out_h
= h
*2; count
=50; // 3
160 out_w
= w
*3; out_h
= h
*3; count
=2; srgb
=0; // 4
162 out_w
= w
*3; out_h
= h
*3; count
=2; // 5 // this is dominated by linear->sRGB conversion
165 output_pixels
= (unsigned char*) malloc(out_w
*out_h
*n
);
166 for (i
=0; i
< count
; ++i
)
168 stbir_resize_uint8_srgb(input_pixels
, w
, h
, 0, output_pixels
, out_w
, out_h
, 0, n
,-1,0);
170 stbir_resize(input_pixels
, w
, h
, 0, output_pixels
, out_w
, out_h
, 0, STBIR_TYPE_UINT8
, n
,-1, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_DEFAULT
, STBIR_FILTER_DEFAULT
, STBIR_COLORSPACE_LINEAR
, NULL
);
174 void test_suite(int argc
, char **argv
);
176 int main(int argc
, char** argv
)
178 //resizer(argc, argv);
179 //performance(argc, argv);
181 test_suite(argc
, argv
);
185 void resize_image(const char* filename
, float width_percent
, float height_percent
, stbir_filter filter
, stbir_edge edge
, stbir_colorspace colorspace
, const char* output_filename
)
189 unsigned char* input_data
= stbi_load(filename
, &w
, &h
, &n
, 0);
192 printf("Input image could not be loaded\n");
196 int out_w
= (int)(w
* width_percent
);
197 int out_h
= (int)(h
* height_percent
);
199 unsigned char* output_data
= (unsigned char*)malloc(out_w
* out_h
* n
);
201 stbir_resize(input_data
, w
, h
, 0, output_data
, out_w
, out_h
, 0, STBIR_TYPE_UINT8
, n
, STBIR_ALPHA_CHANNEL_NONE
, 0, edge
, edge
, filter
, filter
, colorspace
, &g_context
);
203 stbi_image_free(input_data
);
205 stbi_write_png(output_filename
, out_w
, out_h
, n
, output_data
, 0);
210 template <typename F
, typename T
>
211 void convert_image(const F
* input
, T
* output
, int length
)
213 double f
= (pow(2.0, 8.0 * sizeof(T
)) - 1) / (pow(2.0, 8.0 * sizeof(F
)) - 1);
214 for (int i
= 0; i
< length
; i
++)
215 output
[i
] = (T
)(((double)input
[i
]) * f
);
218 template <typename T
>
219 void test_format(const char* file
, float width_percent
, float height_percent
, stbir_datatype type
, stbir_colorspace colorspace
)
222 unsigned char* input_data
= stbi_load(file
, &w
, &h
, &n
, 0);
224 if (input_data
== NULL
)
228 int new_w
= (int)(w
* width_percent
);
229 int new_h
= (int)(h
* height_percent
);
231 T
* T_data
= (T
*)malloc(w
* h
* n
* sizeof(T
));
232 memset(T_data
, 0, w
*h
*n
*sizeof(T
));
233 convert_image
<unsigned char, T
>(input_data
, T_data
, w
* h
* n
);
235 T
* output_data
= (T
*)malloc(new_w
* new_h
* n
* sizeof(T
));
237 stbir_resize(T_data
, w
, h
, 0, output_data
, new_w
, new_h
, 0, type
, n
, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_CATMULLROM
, STBIR_FILTER_CATMULLROM
, colorspace
, &g_context
);
240 stbi_image_free(input_data
);
242 unsigned char* char_data
= (unsigned char*)malloc(new_w
* new_h
* n
* sizeof(char));
243 convert_image
<T
, unsigned char>(output_data
, char_data
, new_w
* new_h
* n
);
246 sprintf(output
, "test-output/type-%d-%d-%d-%d-%s", type
, colorspace
, new_w
, new_h
, file
);
247 stbi_write_png(output
, new_w
, new_h
, n
, char_data
, 0);
253 void convert_image_float(const unsigned char* input
, float* output
, int length
)
255 for (int i
= 0; i
< length
; i
++)
256 output
[i
] = ((float)input
[i
])/255;
259 void convert_image_float(const float* input
, unsigned char* output
, int length
)
261 for (int i
= 0; i
< length
; i
++)
262 output
[i
] = (unsigned char)(stbir__saturate(input
[i
]) * 255);
265 void test_float(const char* file
, float width_percent
, float height_percent
, stbir_datatype type
, stbir_colorspace colorspace
)
268 unsigned char* input_data
= stbi_load(file
, &w
, &h
, &n
, 0);
270 if (input_data
== NULL
)
273 int new_w
= (int)(w
* width_percent
);
274 int new_h
= (int)(h
* height_percent
);
276 float* T_data
= (float*)malloc(w
* h
* n
* sizeof(float));
277 convert_image_float(input_data
, T_data
, w
* h
* n
);
279 float* output_data
= (float*)malloc(new_w
* new_h
* n
* sizeof(float));
281 stbir_resize_float_generic(T_data
, w
, h
, 0, output_data
, new_w
, new_h
, 0, n
, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_CLAMP
, STBIR_FILTER_CATMULLROM
, colorspace
, &g_context
);
284 stbi_image_free(input_data
);
286 unsigned char* char_data
= (unsigned char*)malloc(new_w
* new_h
* n
* sizeof(char));
287 convert_image_float(output_data
, char_data
, new_w
* new_h
* n
);
290 sprintf(output
, "test-output/type-%d-%d-%d-%d-%s", type
, colorspace
, new_w
, new_h
, file
);
291 stbi_write_png(output
, new_w
, new_h
, n
, char_data
, 0);
297 void test_channels(const char* file
, float width_percent
, float height_percent
, int channels
)
300 unsigned char* input_data
= stbi_load(file
, &w
, &h
, &n
, 0);
302 if (input_data
== NULL
)
305 int new_w
= (int)(w
* width_percent
);
306 int new_h
= (int)(h
* height_percent
);
308 unsigned char* channels_data
= (unsigned char*)malloc(w
* h
* channels
* sizeof(unsigned char));
310 for (int i
= 0; i
< w
* h
; i
++)
312 int input_position
= i
* n
;
313 int output_position
= i
* channels
;
315 for (int c
= 0; c
< channels
; c
++)
316 channels_data
[output_position
+ c
] = input_data
[input_position
+ stbir__min(c
, n
)];
319 unsigned char* output_data
= (unsigned char*)malloc(new_w
* new_h
* channels
* sizeof(unsigned char));
321 stbir_resize_uint8_srgb(channels_data
, w
, h
, 0, output_data
, new_w
, new_h
, 0, channels
, STBIR_ALPHA_CHANNEL_NONE
, 0);
324 stbi_image_free(input_data
);
327 sprintf(output
, "test-output/channels-%d-%d-%d-%s", channels
, new_w
, new_h
, file
);
328 stbi_write_png(output
, new_w
, new_h
, channels
, output_data
, 0);
333 void test_subpixel(const char* file
, float width_percent
, float height_percent
, float s1
, float t1
)
336 unsigned char* input_data
= stbi_load(file
, &w
, &h
, &n
, 0);
338 if (input_data
== NULL
)
341 s1
= ((float)w
- 1 + s1
)/w
;
342 t1
= ((float)h
- 1 + t1
)/h
;
344 int new_w
= (int)(w
* width_percent
);
345 int new_h
= (int)(h
* height_percent
);
347 unsigned char* output_data
= (unsigned char*)malloc(new_w
* new_h
* n
* sizeof(unsigned char));
349 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
, 0, 0, s1
, t1
);
351 stbi_image_free(input_data
);
354 sprintf(output
, "test-output/subpixel-%d-%d-%f-%f-%s", new_w
, new_h
, s1
, t1
, file
);
355 stbi_write_png(output
, new_w
, new_h
, n
, output_data
, 0);
360 void test_subpixel_region(const char* file
, float width_percent
, float height_percent
, float s0
, float t0
, float s1
, float t1
)
363 unsigned char* input_data
= stbi_load(file
, &w
, &h
, &n
, 0);
365 if (input_data
== NULL
)
368 int new_w
= (int)(w
* width_percent
);
369 int new_h
= (int)(h
* height_percent
);
371 unsigned char* output_data
= (unsigned char*)malloc(new_w
* new_h
* n
* sizeof(unsigned char));
373 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
);
375 stbi_image_free(input_data
);
378 sprintf(output
, "test-output/subpixel-region-%d-%d-%f-%f-%f-%f-%s", new_w
, new_h
, s0
, t0
, s1
, t1
, file
);
379 stbi_write_png(output
, new_w
, new_h
, n
, output_data
, 0);
384 void test_subpixel_command(const char* file
, float width_percent
, float height_percent
, float x_scale
, float y_scale
, float x_offset
, float y_offset
)
387 unsigned char* input_data
= stbi_load(file
, &w
, &h
, &n
, 0);
389 if (input_data
== NULL
)
392 int new_w
= (int)(w
* width_percent
);
393 int new_h
= (int)(h
* height_percent
);
395 unsigned char* output_data
= (unsigned char*)malloc(new_w
* new_h
* n
* sizeof(unsigned char));
397 stbir_resize_subpixel(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
, x_scale
, y_scale
, x_offset
, y_offset
);
399 stbi_image_free(input_data
);
402 sprintf(output
, "test-output/subpixel-command-%d-%d-%f-%f-%f-%f-%s", new_w
, new_h
, x_scale
, y_scale
, x_offset
, y_offset
, file
);
403 stbi_write_png(output
, new_w
, new_h
, n
, output_data
, 0);
408 unsigned int* pixel(unsigned int* buffer
, int x
, int y
, int c
, int w
, int n
)
410 return &buffer
[y
*w
*n
+ x
*n
+ c
];
415 unsigned int input
[2 * 2 * 4];
416 unsigned int output
[1 * 1 * 4];
417 unsigned int output2
[2 * 2 * 4];
419 memset(input
, 0, sizeof(input
));
421 // First a test to make sure premul is working properly.
423 // Top left - solid red
424 *pixel(input
, 0, 0, 0, 2, 4) = 255;
425 *pixel(input
, 0, 0, 3, 2, 4) = 255;
427 // Bottom left - solid red
428 *pixel(input
, 0, 1, 0, 2, 4) = 255;
429 *pixel(input
, 0, 1, 3, 2, 4) = 255;
431 // Top right - transparent green
432 *pixel(input
, 1, 0, 1, 2, 4) = 255;
433 *pixel(input
, 1, 0, 3, 2, 4) = 25;
435 // Bottom right - transparent green
436 *pixel(input
, 1, 1, 1, 2, 4) = 255;
437 *pixel(input
, 1, 1, 3, 2, 4) = 25;
439 stbir_resize(input
, 2, 2, 0, output
, 1, 1, 0, STBIR_TYPE_UINT32
, 4, 3, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_BOX
, STBIR_FILTER_BOX
, STBIR_COLORSPACE_LINEAR
, &g_context
);
441 float r
= (float)255 / 4294967296;
442 float g
= (float)255 / 4294967296;
443 float ra
= (float)255 / 4294967296;
444 float ga
= (float)25 / 4294967296;
445 float a
= (ra
+ ga
) / 2;
447 STBIR_ASSERT(output
[0] == (unsigned int)(r
* ra
/ 2 / a
* 4294967296 + 0.5f
)); // 232
448 STBIR_ASSERT(output
[1] == (unsigned int)(g
* ga
/ 2 / a
* 4294967296 + 0.5f
)); // 23
449 STBIR_ASSERT(output
[2] == 0);
450 STBIR_ASSERT(output
[3] == (unsigned int)(a
* 4294967296 + 0.5f
)); // 140
452 // Now a test to make sure it doesn't clobber existing values.
454 // Top right - completely transparent green
455 *pixel(input
, 1, 0, 1, 2, 4) = 255;
456 *pixel(input
, 1, 0, 3, 2, 4) = 0;
458 // Bottom right - completely transparent green
459 *pixel(input
, 1, 1, 1, 2, 4) = 255;
460 *pixel(input
, 1, 1, 3, 2, 4) = 0;
462 stbir_resize(input
, 2, 2, 0, output2
, 2, 2, 0, STBIR_TYPE_UINT32
, 4, 3, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_BOX
, STBIR_FILTER_BOX
, STBIR_COLORSPACE_LINEAR
, &g_context
);
464 STBIR_ASSERT(*pixel(output2
, 0, 0, 0, 2, 4) == 255);
465 STBIR_ASSERT(*pixel(output2
, 0, 0, 1, 2, 4) == 0);
466 STBIR_ASSERT(*pixel(output2
, 0, 0, 2, 2, 4) == 0);
467 STBIR_ASSERT(*pixel(output2
, 0, 0, 3, 2, 4) == 255);
469 STBIR_ASSERT(*pixel(output2
, 0, 1, 0, 2, 4) == 255);
470 STBIR_ASSERT(*pixel(output2
, 0, 1, 1, 2, 4) == 0);
471 STBIR_ASSERT(*pixel(output2
, 0, 1, 2, 2, 4) == 0);
472 STBIR_ASSERT(*pixel(output2
, 0, 1, 3, 2, 4) == 255);
474 STBIR_ASSERT(*pixel(output2
, 1, 0, 0, 2, 4) == 0);
475 STBIR_ASSERT(*pixel(output2
, 1, 0, 1, 2, 4) == 255);
476 STBIR_ASSERT(*pixel(output2
, 1, 0, 2, 2, 4) == 0);
477 STBIR_ASSERT(*pixel(output2
, 1, 0, 3, 2, 4) == 0);
479 STBIR_ASSERT(*pixel(output2
, 1, 1, 0, 2, 4) == 0);
480 STBIR_ASSERT(*pixel(output2
, 1, 1, 1, 2, 4) == 255);
481 STBIR_ASSERT(*pixel(output2
, 1, 1, 2, 2, 4) == 0);
482 STBIR_ASSERT(*pixel(output2
, 1, 1, 3, 2, 4) == 0);
485 // test that splitting a pow-2 image into tiles produces identical results
486 void test_subpixel_1()
488 unsigned char image
[8 * 8];
492 for (int i
= 0; i
< sizeof(image
); i
++)
493 image
[i
] = mtrand() & 255;
495 unsigned char output_data
[16 * 16];
497 stbir_resize_region(image
, 8, 8, 0, output_data
, 16, 16, 0, STBIR_TYPE_UINT8
, 1, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_CATMULLROM
, STBIR_FILTER_CATMULLROM
, STBIR_COLORSPACE_SRGB
, &g_context
, 0, 0, 1, 1);
499 unsigned char output_left
[8 * 16];
500 unsigned char output_right
[8 * 16];
502 stbir_resize_region(image
, 8, 8, 0, output_left
, 8, 16, 0, STBIR_TYPE_UINT8
, 1, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_CATMULLROM
, STBIR_FILTER_CATMULLROM
, STBIR_COLORSPACE_SRGB
, &g_context
, 0, 0, 0.5f
, 1);
503 stbir_resize_region(image
, 8, 8, 0, output_right
, 8, 16, 0, STBIR_TYPE_UINT8
, 1, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_CATMULLROM
, STBIR_FILTER_CATMULLROM
, STBIR_COLORSPACE_SRGB
, &g_context
, 0.5f
, 0, 1, 1);
505 for (int x
= 0; x
< 8; x
++)
507 for (int y
= 0; y
< 16; y
++)
509 STBIR_ASSERT(output_data
[y
* 16 + x
] == output_left
[y
* 8 + x
]);
510 STBIR_ASSERT(output_data
[y
* 16 + x
+ 8] == output_right
[y
* 8 + x
]);
514 stbir_resize_subpixel(image
, 8, 8, 0, output_left
, 8, 16, 0, STBIR_TYPE_UINT8
, 1, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_CATMULLROM
, STBIR_FILTER_CATMULLROM
, STBIR_COLORSPACE_SRGB
, &g_context
, 2, 2, 0, 0);
515 stbir_resize_subpixel(image
, 8, 8, 0, output_right
, 8, 16, 0, STBIR_TYPE_UINT8
, 1, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_CATMULLROM
, STBIR_FILTER_CATMULLROM
, STBIR_COLORSPACE_SRGB
, &g_context
, 2, 2, 8, 0);
517 {for (int x
= 0; x
< 8; x
++)
519 for (int y
= 0; y
< 16; y
++)
521 STBIR_ASSERT(output_data
[y
* 16 + x
] == output_left
[y
* 8 + x
]);
522 STBIR_ASSERT(output_data
[y
* 16 + x
+ 8] == output_right
[y
* 8 + x
]);
527 // test that replicating an image and using a subtile of it produces same results as wraparound
528 void test_subpixel_2()
530 unsigned char image
[8 * 8];
534 for (int i
= 0; i
< sizeof(image
); i
++)
535 image
[i
] = mtrand() & 255;
537 unsigned char large_image
[32 * 32];
539 for (int x
= 0; x
< 8; x
++)
541 for (int y
= 0; y
< 8; y
++)
543 for (int i
= 0; i
< 4; i
++)
545 for (int j
= 0; j
< 4; j
++)
546 large_image
[j
*4*8*8 + i
*8 + y
*4*8 + x
] = image
[y
*8 + x
];
551 unsigned char output_data_1
[16 * 16];
552 unsigned char output_data_2
[16 * 16];
554 stbir_resize(image
, 8, 8, 0, output_data_1
, 16, 16, 0, STBIR_TYPE_UINT8
, 1, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_WRAP
, STBIR_EDGE_WRAP
, STBIR_FILTER_CATMULLROM
, STBIR_FILTER_CATMULLROM
, STBIR_COLORSPACE_SRGB
, &g_context
);
555 stbir_resize_region(large_image
, 32, 32, 0, output_data_2
, 16, 16, 0, STBIR_TYPE_UINT8
, 1, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_WRAP
, STBIR_EDGE_WRAP
, STBIR_FILTER_CATMULLROM
, STBIR_FILTER_CATMULLROM
, STBIR_COLORSPACE_SRGB
, &g_context
, 0.25f
, 0.25f
, 0.5f
, 0.5f
);
557 {for (int x
= 0; x
< 16; x
++)
559 for (int y
= 0; y
< 16; y
++)
560 STBIR_ASSERT(output_data_1
[y
* 16 + x
] == output_data_2
[y
* 16 + x
]);
563 stbir_resize_subpixel(large_image
, 32, 32, 0, output_data_2
, 16, 16, 0, STBIR_TYPE_UINT8
, 1, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_WRAP
, STBIR_EDGE_WRAP
, STBIR_FILTER_CATMULLROM
, STBIR_FILTER_CATMULLROM
, STBIR_COLORSPACE_SRGB
, &g_context
, 2, 2, 16, 16);
565 {for (int x
= 0; x
< 16; x
++)
567 for (int y
= 0; y
< 16; y
++)
568 STBIR_ASSERT(output_data_1
[y
* 16 + x
] == output_data_2
[y
* 16 + x
]);
572 // test that 0,0,1,1 subpixel produces same result as no-rect
573 void test_subpixel_3()
575 unsigned char image
[8 * 8];
579 for (int i
= 0; i
< sizeof(image
); i
++)
580 image
[i
] = mtrand() & 255;
582 unsigned char output_data_1
[32 * 32];
583 unsigned char output_data_2
[32 * 32];
585 stbir_resize_region(image
, 8, 8, 0, output_data_1
, 32, 32, 0, STBIR_TYPE_UINT8
, 1, 0, STBIR_ALPHA_CHANNEL_NONE
, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_CATMULLROM
, STBIR_FILTER_CATMULLROM
, STBIR_COLORSPACE_LINEAR
, NULL
, 0, 0, 1, 1);
586 stbir_resize_uint8(image
, 8, 8, 0, output_data_2
, 32, 32, 0, 1);
588 for (int x
= 0; x
< 32; x
++)
590 for (int y
= 0; y
< 32; y
++)
591 STBIR_ASSERT(output_data_1
[y
* 32 + x
] == output_data_2
[y
* 32 + x
]);
594 stbir_resize_subpixel(image
, 8, 8, 0, output_data_1
, 32, 32, 0, STBIR_TYPE_UINT8
, 1, 0, STBIR_ALPHA_CHANNEL_NONE
, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_CATMULLROM
, STBIR_FILTER_CATMULLROM
, STBIR_COLORSPACE_LINEAR
, NULL
, 4, 4, 0, 0);
596 {for (int x
= 0; x
< 32; x
++)
598 for (int y
= 0; y
< 32; y
++)
599 STBIR_ASSERT(output_data_1
[y
* 32 + x
] == output_data_2
[y
* 32 + x
]);
603 // test that 1:1 resample using s,t=0,0,1,1 with bilinear produces original image
604 void test_subpixel_4()
606 unsigned char image
[8 * 8];
610 for (int i
= 0; i
< sizeof(image
); i
++)
611 image
[i
] = mtrand() & 255;
613 unsigned char output
[8 * 8];
615 stbir_resize_region(image
, 8, 8, 0, output
, 8, 8, 0, STBIR_TYPE_UINT8
, 1, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_TRIANGLE
, STBIR_FILTER_TRIANGLE
, STBIR_COLORSPACE_LINEAR
, &g_context
, 0, 0, 1, 1);
616 STBIR_ASSERT(memcmp(image
, output
, 8 * 8) == 0);
618 stbir_resize_subpixel(image
, 8, 8, 0, output
, 8, 8, 0, STBIR_TYPE_UINT8
, 1, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_TRIANGLE
, STBIR_FILTER_TRIANGLE
, STBIR_COLORSPACE_LINEAR
, &g_context
, 1, 1, 0, 0);
619 STBIR_ASSERT(memcmp(image
, output
, 8 * 8) == 0);
622 static unsigned int image88_int
[8][8];
623 static unsigned char image88
[8][8];
624 static unsigned char output88
[8][8];
625 static unsigned char output44
[4][4];
626 static unsigned char output22
[2][2];
627 static unsigned char output11
[1][1];
629 void resample_88(stbir_filter filter
)
631 stbir_resize_uint8_generic(image88
[0],8,8,0, output88
[0],8,8,0, 1,-1,0, STBIR_EDGE_CLAMP
, filter
, STBIR_COLORSPACE_LINEAR
, NULL
);
632 stbir_resize_uint8_generic(image88
[0],8,8,0, output44
[0],4,4,0, 1,-1,0, STBIR_EDGE_CLAMP
, filter
, STBIR_COLORSPACE_LINEAR
, NULL
);
633 stbir_resize_uint8_generic(image88
[0],8,8,0, output22
[0],2,2,0, 1,-1,0, STBIR_EDGE_CLAMP
, filter
, STBIR_COLORSPACE_LINEAR
, NULL
);
634 stbir_resize_uint8_generic(image88
[0],8,8,0, output11
[0],1,1,0, 1,-1,0, STBIR_EDGE_CLAMP
, filter
, STBIR_COLORSPACE_LINEAR
, NULL
);
637 void verify_box(void)
641 resample_88(STBIR_FILTER_BOX
);
643 for (i
=0; i
< sizeof(image88
); ++i
)
644 STBIR_ASSERT(image88
[0][i
] == output88
[0][i
]);
647 for (j
=0; j
< 4; ++j
)
648 for (i
=0; i
< 4; ++i
) {
649 int n
= image88
[j
*2+0][i
*2+0]
650 + image88
[j
*2+0][i
*2+1]
651 + image88
[j
*2+1][i
*2+0]
652 + image88
[j
*2+1][i
*2+1];
653 STBIR_ASSERT(output44
[j
][i
] == ((n
+2)>>2) || output44
[j
][i
] == ((n
+1)>>2)); // can't guarantee exact rounding due to numerical precision
656 STBIR_ASSERT(output11
[0][0] == ((t
+32)>>6) || output11
[0][0] == ((t
+31)>>6)); // can't guarantee exact rounding due to numerical precision
659 void verify_filter_normalized(stbir_filter filter
, int output_size
, unsigned int value
)
662 unsigned int output
[64];
664 stbir_resize(image88_int
[0], 8, 8, 0, output
, output_size
, output_size
, 0, STBIR_TYPE_UINT32
, 1, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, filter
, filter
, STBIR_COLORSPACE_LINEAR
, NULL
);
666 for (j
= 0; j
< output_size
; ++j
)
667 for (i
= 0; i
< output_size
; ++i
)
668 STBIR_ASSERT(value
== output
[j
*output_size
+ i
]);
671 float round2(float f
)
673 return (float) floor(f
+0.5f
); // round() isn't C standard pre-C99
676 void test_filters(void)
682 for (i
=0; i
< sizeof(image88
); ++i
)
683 image88
[0][i
] = mtrand() & 255;
686 for (i
=0; i
< sizeof(image88
); ++i
)
691 for (j
=0; j
< 8; ++j
)
692 for (i
=0; i
< 8; ++i
)
693 image88
[j
][i
] = (j
^i
)&1 ? 255 : 0;
696 for (j
=0; j
< 8; ++j
)
697 for (i
=0; i
< 8; ++i
)
698 image88
[j
][i
] = i
&2 ? 255 : 0;
703 for (j
= 0; j
< 8; ++j
)
704 for (i
= 0; i
< 8; ++i
)
705 image88_int
[j
][i
] = value
;
707 verify_filter_normalized(STBIR_FILTER_BOX
, 8, value
);
708 verify_filter_normalized(STBIR_FILTER_TRIANGLE
, 8, value
);
709 verify_filter_normalized(STBIR_FILTER_CUBICBSPLINE
, 8, value
);
710 verify_filter_normalized(STBIR_FILTER_CATMULLROM
, 8, value
);
711 verify_filter_normalized(STBIR_FILTER_MITCHELL
, 8, value
);
713 verify_filter_normalized(STBIR_FILTER_BOX
, 4, value
);
714 verify_filter_normalized(STBIR_FILTER_TRIANGLE
, 4, value
);
715 verify_filter_normalized(STBIR_FILTER_CUBICBSPLINE
, 4, value
);
716 verify_filter_normalized(STBIR_FILTER_CATMULLROM
, 4, value
);
717 verify_filter_normalized(STBIR_FILTER_MITCHELL
, 4, value
);
719 verify_filter_normalized(STBIR_FILTER_BOX
, 2, value
);
720 verify_filter_normalized(STBIR_FILTER_TRIANGLE
, 2, value
);
721 verify_filter_normalized(STBIR_FILTER_CUBICBSPLINE
, 2, value
);
722 verify_filter_normalized(STBIR_FILTER_CATMULLROM
, 2, value
);
723 verify_filter_normalized(STBIR_FILTER_MITCHELL
, 2, value
);
725 verify_filter_normalized(STBIR_FILTER_BOX
, 1, value
);
726 verify_filter_normalized(STBIR_FILTER_TRIANGLE
, 1, value
);
727 verify_filter_normalized(STBIR_FILTER_CUBICBSPLINE
, 1, value
);
728 verify_filter_normalized(STBIR_FILTER_CATMULLROM
, 1, value
);
729 verify_filter_normalized(STBIR_FILTER_MITCHELL
, 1, value
);
732 // This test is designed to produce coefficients that are very badly denormalized.
733 unsigned int v
= 556;
735 unsigned int input
[100 * 100];
736 unsigned int output
[11 * 11];
738 for (j
= 0; j
< 100 * 100; ++j
)
741 stbir_resize(input
, 100, 100, 0, output
, 11, 11, 0, STBIR_TYPE_UINT32
, 1, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_TRIANGLE
, STBIR_FILTER_TRIANGLE
, STBIR_COLORSPACE_LINEAR
, NULL
);
743 for (j
= 0; j
< 11 * 11; ++j
)
744 STBIR_ASSERT(v
== output
[j
]);
748 // Now test the trapezoid filter for downsampling.
749 unsigned int input
[3 * 1];
750 unsigned int output
[2 * 1];
756 stbir_resize(input
, 3, 1, 0, output
, 2, 1, 0, STBIR_TYPE_UINT32
, 1, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_BOX
, STBIR_FILTER_BOX
, STBIR_COLORSPACE_LINEAR
, NULL
);
758 STBIR_ASSERT(output
[0] == (unsigned int)round2((float)(input
[0] * 2 + input
[1]) / 3));
759 STBIR_ASSERT(output
[1] == (unsigned int)round2((float)(input
[2] * 2 + input
[1]) / 3));
761 stbir_resize(input
, 1, 3, 0, output
, 1, 2, 0, STBIR_TYPE_UINT32
, 1, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_BOX
, STBIR_FILTER_BOX
, STBIR_COLORSPACE_LINEAR
, NULL
);
763 STBIR_ASSERT(output
[0] == (unsigned int)round2((float)(input
[0] * 2 + input
[1]) / 3));
764 STBIR_ASSERT(output
[1] == (unsigned int)round2((float)(input
[2] * 2 + input
[1]) / 3));
768 // Now test the trapezoid filter for upsampling.
769 unsigned int input
[2 * 1];
770 unsigned int output
[3 * 1];
775 stbir_resize(input
, 2, 1, 0, output
, 3, 1, 0, STBIR_TYPE_UINT32
, 1, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_BOX
, STBIR_FILTER_BOX
, STBIR_COLORSPACE_LINEAR
, NULL
);
777 STBIR_ASSERT(output
[0] == input
[0]);
778 STBIR_ASSERT(output
[1] == (input
[0] + input
[1]) / 2);
779 STBIR_ASSERT(output
[2] == input
[1]);
781 stbir_resize(input
, 1, 2, 0, output
, 1, 3, 0, STBIR_TYPE_UINT32
, 1, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_BOX
, STBIR_FILTER_BOX
, STBIR_COLORSPACE_LINEAR
, NULL
);
783 STBIR_ASSERT(output
[0] == input
[0]);
784 STBIR_ASSERT(output
[1] == (input
[0] + input
[1]) / 2);
785 STBIR_ASSERT(output
[2] == input
[1]);
790 unsigned char input
[64][64];
791 unsigned char output
[16][16];
793 for (j
=0; j
< 64; ++j
)
794 for (i
=0; i
< 64; ++i
)
795 input
[j
][i
] = (i
^j
)&1 ? 255 : 0;
796 stbir_resize_uint8_generic(input
[0], 64, 64, 0, output
[0],16,16,0, 1,-1,0,STBIR_EDGE_WRAP
,STBIR_FILTER_DEFAULT
,STBIR_COLORSPACE_LINEAR
,0);
797 for (j
=0; j
< 16; ++j
)
798 for (i
=0; i
< 16; ++i
)
799 STBIR_ASSERT(output
[j
][i
] == 128);
800 stbir_resize_uint8_srgb_edgemode(input
[0], 64, 64, 0, output
[0],16,16,0, 1,-1,0,STBIR_EDGE_WRAP
);
801 for (j
=0; j
< 16; ++j
)
802 for (i
=0; i
< 16; ++i
)
803 STBIR_ASSERT(output
[j
][i
] == 188);
809 // Test trapezoid box filter
810 unsigned char input
[2 * 1];
811 unsigned char output
[127 * 1];
816 stbir_resize(input
, 2, 1, 0, output
, 127, 1, 0, STBIR_TYPE_UINT8
, 1, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_BOX
, STBIR_FILTER_BOX
, STBIR_COLORSPACE_LINEAR
, NULL
);
817 STBIR_ASSERT(output
[0] == 0);
818 STBIR_ASSERT(output
[127 / 2 - 1] == 0);
819 STBIR_ASSERT(output
[127 / 2] == 128);
820 STBIR_ASSERT(output
[127 / 2 + 1] == 255);
821 STBIR_ASSERT(output
[126] == 255);
822 stbi_write_png("test-output/trapezoid-upsample-horizontal.png", 127, 1, 1, output
, 0);
824 stbir_resize(input
, 1, 2, 0, output
, 1, 127, 0, STBIR_TYPE_UINT8
, 1, STBIR_ALPHA_CHANNEL_NONE
, 0, STBIR_EDGE_CLAMP
, STBIR_EDGE_CLAMP
, STBIR_FILTER_BOX
, STBIR_FILTER_BOX
, STBIR_COLORSPACE_LINEAR
, NULL
);
825 STBIR_ASSERT(output
[0] == 0);
826 STBIR_ASSERT(output
[127 / 2 - 1] == 0);
827 STBIR_ASSERT(output
[127 / 2] == 128);
828 STBIR_ASSERT(output
[127 / 2 + 1] == 255);
829 STBIR_ASSERT(output
[126] == 255);
830 stbi_write_png("test-output/trapezoid-upsample-vertical.png", 1, 127, 1, output
, 0);
834 #define UMAX32 4294967295U
836 static void write32(char *filename
, stbir_uint32
*output
, int w
, int h
)
838 stbir_uint8
*data
= (stbir_uint8
*) malloc(w
*h
*3);
839 for (int i
=0; i
< w
*h
*3; ++i
)
840 data
[i
] = output
[i
]>>24;
841 stbi_write_png(filename
, w
, h
, 3, data
, 0);
845 static void test_32(void)
847 int w
=100,h
=120,x
,y
, out_w
,out_h
;
848 stbir_uint32
*input
= (stbir_uint32
*) malloc(4 * 3 * w
* h
);
849 stbir_uint32
*output
= (stbir_uint32
*) malloc(4 * 3 * 3*w
* 3*h
);
850 for (y
=0; y
< h
; ++y
) {
851 for (x
=0; x
< w
; ++x
) {
852 input
[y
*3*w
+ x
*3 + 0] = x
* ( UMAX32
/w
);
853 input
[y
*3*w
+ x
*3 + 1] = y
* ( UMAX32
/h
);
854 input
[y
*3*w
+ x
*3 + 2] = UMAX32
/2;
859 stbir_resize(input
,w
,h
,0,output
,out_w
,out_h
,0,STBIR_TYPE_UINT32
,3,-1,0,STBIR_EDGE_CLAMP
,STBIR_EDGE_CLAMP
,STBIR_FILTER_DEFAULT
,STBIR_FILTER_DEFAULT
,STBIR_COLORSPACE_LINEAR
,NULL
);
860 write32("test-output/seantest_1.png", output
,out_w
,out_h
);
864 stbir_resize(input
,w
,h
,0,output
,out_w
,out_h
,0,STBIR_TYPE_UINT32
,3,-1,0,STBIR_EDGE_CLAMP
,STBIR_EDGE_CLAMP
,STBIR_FILTER_DEFAULT
,STBIR_FILTER_DEFAULT
,STBIR_COLORSPACE_LINEAR
,NULL
);
865 write32("test-output/seantest_2.png", output
,out_w
,out_h
);
869 void test_suite(int argc
, char **argv
)
874 _mkdir("test-output");
879 barbara
= "barbara.png";
881 // check what cases we need normalization for
885 for (x
= -1; x
< 1; x
+= 0.05f
) {
886 float sums
[5] = { 0 };
888 for (o
= -5; o
<= 5; ++o
) {
889 sums
[0] += stbir__filter_mitchell(x
+ o
, 1);
890 sums
[1] += stbir__filter_catmullrom(x
+ o
, 1);
891 sums
[2] += stbir__filter_cubic(x
+ o
, 1);
892 sums
[3] += stbir__filter_triangle(x
+ o
, 1);
893 sums
[4] += stbir__filter_trapezoid(x
+ o
, 0.5f
);
895 for (i
= 0; i
< 5; ++i
)
896 STBIR_ASSERT(sums
[i
] >= 1.0 - 0.001 && sums
[i
] <= 1.0 + 0.001);
900 for (y
= 0.11f
; y
< 1; y
+= 0.01f
) { // Step
901 for (x
= -1; x
< 1; x
+= 0.05f
) { // Phase
902 float sums
[5] = { 0 };
904 for (o
= -5; o
<= 5; o
+= y
) {
905 sums
[0] += y
* stbir__filter_mitchell(x
+ o
, 1);
906 sums
[1] += y
* stbir__filter_catmullrom(x
+ o
, 1);
907 sums
[2] += y
* stbir__filter_cubic(x
+ o
, 1);
908 sums
[4] += y
* stbir__filter_trapezoid(x
+ o
, 0.5f
);
909 sums
[3] += y
* stbir__filter_triangle(x
+ o
, 1);
911 for (i
= 0; i
< 3; ++i
)
912 STBIR_ASSERT(sums
[i
] >= 1.0 - 0.0170 && sums
[i
] <= 1.0 + 0.0170);
919 #if 0 // linear_to_srgb_uchar table
920 for (i
=0; i
< 256; ++i
) {
921 float f
= stbir__srgb_to_linear((i
-0.5f
)/255.0f
);
922 printf("%9d, ", (int) ((f
) * (1<<28)));
928 // old tests that hacky fix worked on - test that
929 // every uint8 maps to itself
930 for (i
= 0; i
< 256; i
++) {
931 float f
= stbir__srgb_to_linear(float(i
) / 255);
932 int n
= stbir__linear_to_srgb_uchar(f
);
933 STBIR_ASSERT(n
== i
);
936 // new tests that hacky fix failed for - test that
937 // values adjacent to uint8 round to nearest uint8
938 for (i
= 0; i
< 256; i
++) {
939 for (float y
= -0.42f
; y
<= 0.42f
; y
+= 0.01f
) {
940 float f
= stbir__srgb_to_linear((i
+y
) / 255.0f
);
941 int n
= stbir__linear_to_srgb_uchar(f
);
942 STBIR_ASSERT(n
== i
);
957 // Some tests to make sure errors don't pop up with strange filter/dimension combinations.
958 stbir_resize(image88
, 8, 8, 0, output88
, 4, 16, 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
);
959 stbir_resize(image88
, 8, 8, 0, output88
, 4, 16, 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
);
960 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
);
961 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
);
963 int barbara_width
, barbara_height
, barbara_channels
;
964 stbi_image_free(stbi_load(barbara
, &barbara_width
, &barbara_height
, &barbara_channels
, 0));
968 {for (int i
= 0; i
<= res
; i
++)
970 float t
= (float)i
/res
;
972 float out_scale
= 2.0f
/3;
973 float x_shift
= (barbara_width
*out_scale
- barbara_width
*scale
) * t
;
974 float y_shift
= (barbara_height
*out_scale
- barbara_height
*scale
) * t
;
976 test_subpixel_command(barbara
, scale
, scale
, out_scale
, out_scale
, x_shift
, y_shift
);
980 {for (int i
= 0; i
<= res
; i
++)
982 float t
= (float)i
/res
;
985 float x_shift
= (barbara_width
*out_scale
- barbara_width
*scale
) * t
;
986 float y_shift
= (barbara_height
*out_scale
- barbara_height
*scale
) * t
;
988 test_subpixel_command(barbara
, scale
, scale
, out_scale
, out_scale
, x_shift
, y_shift
);
992 {for (int i
= 0; i
<= res
; i
++)
994 float t
= (float)i
/res
/ 2;
995 test_subpixel_region(barbara
, 0.25f
, 0.25f
, t
, t
, t
+0.5f
, t
+0.5f
);
999 {for (int i
= 0; i
<= res
; i
++)
1001 float t
= (float)i
/res
/ 2;
1002 test_subpixel_region(barbara
, 0.5f
, 0.5f
, t
, t
, t
+0.5f
, t
+0.5f
);
1006 {for (int i
= 0; i
<= res
; i
++)
1008 float t
= (float)i
/res
/ 2;
1009 test_subpixel_region(barbara
, 1, 1, t
, t
, t
+0.5f
, t
+0.5f
);
1012 {for (i
= 0; i
< 10; i
++)
1013 test_subpixel(barbara
, 0.5f
, 0.5f
, (float)i
/ 10, 1);
1016 {for (i
= 0; i
< 10; i
++)
1017 test_subpixel(barbara
, 0.5f
, 0.5f
, 1, (float)i
/ 10);
1020 {for (i
= 0; i
< 10; i
++)
1021 test_subpixel(barbara
, 2, 2, (float)i
/ 10, 1);
1024 {for (i
= 0; i
< 10; i
++)
1025 test_subpixel(barbara
, 2, 2, 1, (float)i
/ 10);
1029 test_channels(barbara
, 0.5f
, 0.5f
, 1);
1030 test_channels(barbara
, 0.5f
, 0.5f
, 2);
1031 test_channels(barbara
, 0.5f
, 0.5f
, 3);
1032 test_channels(barbara
, 0.5f
, 0.5f
, 4);
1034 test_channels(barbara
, 2, 2, 1);
1035 test_channels(barbara
, 2, 2, 2);
1036 test_channels(barbara
, 2, 2, 3);
1037 test_channels(barbara
, 2, 2, 4);
1040 resize_image(barbara
, 2, 2, STBIR_FILTER_BOX
, STBIR_EDGE_CLAMP
, STBIR_COLORSPACE_SRGB
, "test-output/barbara-upsample-nearest.png");
1041 resize_image(barbara
, 2, 2, STBIR_FILTER_TRIANGLE
, STBIR_EDGE_CLAMP
, STBIR_COLORSPACE_SRGB
, "test-output/barbara-upsample-bilinear.png");
1042 resize_image(barbara
, 2, 2, STBIR_FILTER_CUBICBSPLINE
, STBIR_EDGE_CLAMP
, STBIR_COLORSPACE_SRGB
, "test-output/barbara-upsample-bicubic.png");
1043 resize_image(barbara
, 2, 2, STBIR_FILTER_CATMULLROM
, STBIR_EDGE_CLAMP
, STBIR_COLORSPACE_SRGB
, "test-output/barbara-upsample-catmullrom.png");
1044 resize_image(barbara
, 2, 2, STBIR_FILTER_MITCHELL
, STBIR_EDGE_CLAMP
, STBIR_COLORSPACE_SRGB
, "test-output/barbara-upsample-mitchell.png");
1046 resize_image(barbara
, 0.5f
, 0.5f
, STBIR_FILTER_BOX
, STBIR_EDGE_CLAMP
, STBIR_COLORSPACE_SRGB
, "test-output/barbara-downsample-nearest.png");
1047 resize_image(barbara
, 0.5f
, 0.5f
, STBIR_FILTER_TRIANGLE
, STBIR_EDGE_CLAMP
, STBIR_COLORSPACE_SRGB
, "test-output/barbara-downsample-bilinear.png");
1048 resize_image(barbara
, 0.5f
, 0.5f
, STBIR_FILTER_CUBICBSPLINE
, STBIR_EDGE_CLAMP
, STBIR_COLORSPACE_SRGB
, "test-output/barbara-downsample-bicubic.png");
1049 resize_image(barbara
, 0.5f
, 0.5f
, STBIR_FILTER_CATMULLROM
, STBIR_EDGE_CLAMP
, STBIR_COLORSPACE_SRGB
, "test-output/barbara-downsample-catmullrom.png");
1050 resize_image(barbara
, 0.5f
, 0.5f
, STBIR_FILTER_MITCHELL
, STBIR_EDGE_CLAMP
, STBIR_COLORSPACE_SRGB
, "test-output/barbara-downsample-mitchell.png");
1052 {for (i
= 10; i
< 100; i
++)
1055 sprintf(outname
, "test-output/barbara-width-%d.jpg", i
);
1056 resize_image(barbara
, (float)i
/ 100, 1, STBIR_FILTER_CATMULLROM
, STBIR_EDGE_CLAMP
, STBIR_COLORSPACE_SRGB
, outname
);
1059 {for (i
= 110; i
< 500; i
+= 10)
1062 sprintf(outname
, "test-output/barbara-width-%d.jpg", i
);
1063 resize_image(barbara
, (float)i
/ 100, 1, STBIR_FILTER_CATMULLROM
, STBIR_EDGE_CLAMP
, STBIR_COLORSPACE_SRGB
, outname
);
1066 {for (i
= 10; i
< 100; i
++)
1069 sprintf(outname
, "test-output/barbara-height-%d.jpg", i
);
1070 resize_image(barbara
, 1, (float)i
/ 100, STBIR_FILTER_CATMULLROM
, STBIR_EDGE_CLAMP
, STBIR_COLORSPACE_SRGB
, outname
);
1073 {for (i
= 110; i
< 500; i
+= 10)
1076 sprintf(outname
, "test-output/barbara-height-%d.jpg", i
);
1077 resize_image(barbara
, 1, (float)i
/ 100, STBIR_FILTER_CATMULLROM
, STBIR_EDGE_CLAMP
, STBIR_COLORSPACE_SRGB
, outname
);
1080 {for (i
= 50; i
< 200; i
+= 10)
1083 sprintf(outname
, "test-output/barbara-width-height-%d.jpg", i
);
1084 resize_image(barbara
, 100 / (float)i
, (float)i
/ 100, STBIR_FILTER_CATMULLROM
, STBIR_EDGE_CLAMP
, STBIR_COLORSPACE_SRGB
, outname
);
1087 test_format
<unsigned short>(barbara
, 0.5, 2.0, STBIR_TYPE_UINT16
, STBIR_COLORSPACE_SRGB
);
1088 test_format
<unsigned short>(barbara
, 0.5, 2.0, STBIR_TYPE_UINT16
, STBIR_COLORSPACE_LINEAR
);
1089 test_format
<unsigned short>(barbara
, 2.0, 0.5, STBIR_TYPE_UINT16
, STBIR_COLORSPACE_SRGB
);
1090 test_format
<unsigned short>(barbara
, 2.0, 0.5, STBIR_TYPE_UINT16
, STBIR_COLORSPACE_LINEAR
);
1092 test_format
<unsigned int>(barbara
, 0.5, 2.0, STBIR_TYPE_UINT32
, STBIR_COLORSPACE_SRGB
);
1093 test_format
<unsigned int>(barbara
, 0.5, 2.0, STBIR_TYPE_UINT32
, STBIR_COLORSPACE_LINEAR
);
1094 test_format
<unsigned int>(barbara
, 2.0, 0.5, STBIR_TYPE_UINT32
, STBIR_COLORSPACE_SRGB
);
1095 test_format
<unsigned int>(barbara
, 2.0, 0.5, STBIR_TYPE_UINT32
, STBIR_COLORSPACE_LINEAR
);
1097 test_float(barbara
, 0.5, 2.0, STBIR_TYPE_FLOAT
, STBIR_COLORSPACE_SRGB
);
1098 test_float(barbara
, 0.5, 2.0, STBIR_TYPE_FLOAT
, STBIR_COLORSPACE_LINEAR
);
1099 test_float(barbara
, 2.0, 0.5, STBIR_TYPE_FLOAT
, STBIR_COLORSPACE_SRGB
);
1100 test_float(barbara
, 2.0, 0.5, STBIR_TYPE_FLOAT
, STBIR_COLORSPACE_LINEAR
);
1102 // Edge behavior tests
1103 resize_image("hgradient.png", 2, 2, STBIR_FILTER_CATMULLROM
, STBIR_EDGE_CLAMP
, STBIR_COLORSPACE_LINEAR
, "test-output/hgradient-clamp.png");
1104 resize_image("hgradient.png", 2, 2, STBIR_FILTER_CATMULLROM
, STBIR_EDGE_WRAP
, STBIR_COLORSPACE_LINEAR
, "test-output/hgradient-wrap.png");
1106 resize_image("vgradient.png", 2, 2, STBIR_FILTER_CATMULLROM
, STBIR_EDGE_CLAMP
, STBIR_COLORSPACE_LINEAR
, "test-output/vgradient-clamp.png");
1107 resize_image("vgradient.png", 2, 2, STBIR_FILTER_CATMULLROM
, STBIR_EDGE_WRAP
, STBIR_COLORSPACE_LINEAR
, "test-output/vgradient-wrap.png");
1109 resize_image("1px-border.png", 2, 2, STBIR_FILTER_CATMULLROM
, STBIR_EDGE_REFLECT
, STBIR_COLORSPACE_LINEAR
, "test-output/1px-border-reflect.png");
1110 resize_image("1px-border.png", 2, 2, STBIR_FILTER_CATMULLROM
, STBIR_EDGE_CLAMP
, STBIR_COLORSPACE_LINEAR
, "test-output/1px-border-clamp.png");
1113 resize_image("gamma_colors.jpg", .5f
, .5f
, STBIR_FILTER_CATMULLROM
, STBIR_EDGE_REFLECT
, STBIR_COLORSPACE_SRGB
, "test-output/gamma_colors.jpg");
1114 resize_image("gamma_2.2.jpg", .5f
, .5f
, STBIR_FILTER_CATMULLROM
, STBIR_EDGE_REFLECT
, STBIR_COLORSPACE_SRGB
, "test-output/gamma_2.2.jpg");
1115 resize_image("gamma_dalai_lama_gray.jpg", .5f
, .5f
, STBIR_FILTER_CATMULLROM
, STBIR_EDGE_REFLECT
, STBIR_COLORSPACE_SRGB
, "test-output/gamma_dalai_lama_gray.jpg");