| /* |
| |
| * Copyright (c) 2012-2017 The Khronos Group Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "test_engine/test.h" |
| #include <VX/vx.h> |
| #include <VX/vxu.h> |
| |
| #include <math.h> // floorf |
| |
| TESTCASE(Scale, CT_VXContext, ct_setup_vx_context, 0) |
| |
| TEST(Scale, testNodeCreation) |
| { |
| vx_context context = context_->vx_context_; |
| vx_image src_image = 0, dst_image = 0; |
| vx_graph graph = 0; |
| vx_node node = 0; |
| |
| ASSERT_VX_OBJECT(src_image = vxCreateImage(context, 128, 128, VX_DF_IMAGE_U8), VX_TYPE_IMAGE); |
| ASSERT_VX_OBJECT(dst_image = vxCreateImage(context, 128, 128, VX_DF_IMAGE_U8), VX_TYPE_IMAGE); |
| |
| ASSERT_VX_OBJECT(graph = vxCreateGraph(context), VX_TYPE_GRAPH); |
| |
| ASSERT_VX_OBJECT(node = vxScaleImageNode(graph, src_image, dst_image, VX_INTERPOLATION_NEAREST_NEIGHBOR), VX_TYPE_NODE); |
| |
| VX_CALL(vxReleaseNode(&node)); |
| VX_CALL(vxReleaseGraph(&graph)); |
| VX_CALL(vxReleaseImage(&dst_image)); |
| VX_CALL(vxReleaseImage(&src_image)); |
| |
| ASSERT(node == 0); |
| ASSERT(graph == 0); |
| ASSERT(dst_image == 0); |
| ASSERT(src_image == 0); |
| } |
| |
| |
| static CT_Image scale_generate_random(const char* fileName, int width, int height) |
| { |
| CT_Image image; |
| |
| ASSERT_NO_FAILURE_(return 0, |
| image = ct_allocate_ct_image_random(width, height, VX_DF_IMAGE_U8, &CT()->seed_, 0, 256)); |
| |
| return image; |
| } |
| |
| static CT_Image _scale_generate_simple_gradient(int width, int height, int step_x, int step_y, int offset) |
| { |
| CT_Image image = NULL; |
| uint32_t x, y; |
| |
| ASSERT_(return 0, step_x > 0); |
| ASSERT_(return 0, step_y > 0); |
| |
| ASSERT_NO_FAILURE_(return 0, |
| image = ct_allocate_image(width, height, VX_DF_IMAGE_U8)); |
| |
| for (y = 0; y < image->height; y++) |
| { |
| for (x = 0; x < image->width; x++) |
| { |
| uint8_t* ptr = CT_IMAGE_DATA_PTR_8U(image, x, y); |
| int v = offset + (y / step_y) + (x / step_x); |
| *ptr = (uint8_t)v; |
| } |
| } |
| |
| return image; |
| } |
| |
| static CT_Image scale_generate_gradient_2x2(const char* fileName, int width, int height) |
| { |
| return _scale_generate_simple_gradient(width, height, 2, 2, 0); |
| } |
| |
| static CT_Image scale_generate_gradient_16x16(const char* fileName, int width, int height) |
| { |
| return _scale_generate_simple_gradient(width, height, 16, 16, 32); |
| } |
| |
| static CT_Image scale_generate_pattern3x3(const char* fileName, int width, int height) |
| { |
| CT_Image image = NULL; |
| uint32_t x, y; |
| |
| ASSERT_NO_FAILURE_(return 0, |
| image = ct_allocate_image(width, height, VX_DF_IMAGE_U8)); |
| |
| for (y = 0; y < image->height; y++) |
| { |
| for (x = 0; x < image->width; x++) |
| { |
| uint8_t* ptr = CT_IMAGE_DATA_PTR_8U(image, x, y); |
| int v = ((y % 3) == 1 && (x % 3) == 1) ? 0 : 255; |
| *ptr = (uint8_t)v; |
| } |
| } |
| |
| return image; |
| } |
| |
| static CT_Image scale_read_image(const char* fileName, int width, int height) |
| { |
| CT_Image image = NULL; |
| ASSERT_(return 0, width == 0 && height == 0); |
| image = ct_read_image(fileName, 1); |
| ASSERT_(return 0, image); |
| ASSERT_(return 0, image->format == VX_DF_IMAGE_U8); |
| return image; |
| } |
| |
| static vx_int32 ct_image_get_pixel_8u(CT_Image img, int x, int y, vx_border_t border) |
| { |
| if (border.mode == VX_BORDER_UNDEFINED) |
| { |
| if (x < 0 || x >= (int)img->width || y < 0 || y >= (int)img->height) |
| return -1; //border |
| return *CT_IMAGE_DATA_PTR_8U(img, x, y); |
| } |
| else if (border.mode == VX_BORDER_REPLICATE) |
| { |
| return CT_IMAGE_DATA_REPLICATE_8U(img, x, y); |
| } |
| else if (border.mode == VX_BORDER_CONSTANT) |
| { |
| return CT_IMAGE_DATA_CONSTANT_8U(img, x, y, border.constant_value.U8); |
| } |
| else |
| { |
| CT_FAIL_(return -1, "Invalid border type"); |
| } |
| } |
| |
| static int scale_check_pixel(CT_Image src, CT_Image dst, int x, int y, vx_enum interpolation, vx_border_t border) |
| { |
| vx_uint8 res = *CT_IMAGE_DATA_PTR_8U(dst, x, y); |
| vx_float32 x_src = (((vx_float32)x + 0.5f) * (vx_float32)src->width / (vx_float32)dst->width) - 0.5f; |
| vx_float32 y_src = (((vx_float32)y + 0.5f) * (vx_float32)src->height / (vx_float32)dst->height) - 0.5f; |
| int x_min = (int)floorf(x_src), y_min = (int)floorf(y_src); |
| if (interpolation == VX_INTERPOLATION_NEAREST_NEIGHBOR) |
| { |
| int sx, sy; |
| for (sy = -1; sy <= 1; sy++) |
| { |
| for (sx = -1; sx <= 1; sx++) |
| { |
| vx_int32 candidate = 0; |
| ASSERT_NO_FAILURE_(return 0, candidate = ct_image_get_pixel_8u(src, x_min + sx, y_min + sy, border)); |
| if (candidate == -1 || candidate == res) |
| return 1; |
| } |
| } |
| CT_FAIL_(return 0, "Check failed for pixel (%d, %d): %d", x, y, (int)res); |
| } |
| if (interpolation == VX_INTERPOLATION_BILINEAR) |
| { |
| vx_float32 s = x_src - x_min; |
| vx_float32 t = y_src - y_min; |
| vx_int32 p00 = ct_image_get_pixel_8u(src, x_min + 0, y_min + 0, border); |
| vx_int32 p01 = ct_image_get_pixel_8u(src, x_min + 0, y_min + 1, border); |
| vx_int32 p10 = ct_image_get_pixel_8u(src, x_min + 1, y_min + 0, border); |
| vx_int32 p11 = ct_image_get_pixel_8u(src, x_min + 1, y_min + 1, border); |
| vx_float32 ref_float; |
| vx_int32 ref; |
| |
| // If the computed coordinate is very close to the boundary (1e-7), we don't |
| // consider it out-of-bound, in order to handle potential float accuracy errors |
| vx_bool defined = (vx_bool)((p00 != -1) && (p10 != -1) && (p01 != -1) && (p11 != -1)); |
| if (defined == vx_false_e) |
| { |
| vx_bool defined_any = (vx_bool)((p00 != -1) || (p10 != -1) || (p01 != -1) || (p11 != -1)); |
| if (defined_any) |
| { |
| if ((p00 == -1 || p10 == -1) && fabs(t - 1.0) <= 1e-7) |
| p00 = p10 = 0; |
| else if ((p01 == -1 || p11 == -1) && fabs(t - 0.0) <= 1e-7) |
| p01 = p11 = 0; |
| if ((p00 == -1 || p01 == -1) && fabs(s - 1.0) <= 1e-7) |
| p00 = p01 = 0; |
| else if ((p10 == -1 || p11 == -1) && fabs(s - 0.0) <= 1e-7) |
| p10 = p11 = 0; |
| defined = (vx_bool)((p00 != -1) && (p10 != -1) && (p01 != -1) && (p11 != -1)); |
| } |
| } |
| if (defined == vx_false_e) { |
| return 1; |
| } |
| |
| // Compute the expected result (float) |
| ref_float = (1 - s) * (1 - t) * p00 + |
| ( s) * (1 - t) * p10 + |
| (1 - s) * ( t) * p01 + |
| ( s) * ( t) * p11; |
| |
| // Take the nearest integer to avoid problems with casts in case of float rounding errors |
| // (e.g: 30.999999 should give 31, not 30) |
| ref = (vx_int32)(ref_float + 0.5f); |
| |
| // A difference of 1 is allowed |
| if (abs(res - ref) <= 1) { |
| return 1; |
| } |
| |
| return 0; // don't generate failure, we will check num failed pixels later |
| } |
| if (interpolation == VX_INTERPOLATION_AREA) |
| { |
| vx_int32 v_min = 256, v_max = -1; |
| int sx, sy; |
| // check values at 5x5 area |
| for (sy = -2; sy <= 2; sy++) |
| { |
| for (sx = -2; sx <= 2; sx++) |
| { |
| vx_int32 candidate = 0; |
| ASSERT_NO_FAILURE_(return 0, candidate = ct_image_get_pixel_8u(src, x_min + sx, y_min + sy, border)); |
| if (candidate == -1) |
| return 1; |
| if (v_min > candidate) |
| v_min = candidate; |
| if (v_max < candidate) |
| v_max = candidate; |
| } |
| if (v_min <= res && v_max >= res) |
| return 1; |
| } |
| CT_FAIL_(return 0, "Check failed for pixel (%d, %d): %d", x, y, (int)res); |
| } |
| CT_FAIL_(return 0, "NOT IMPLEMENTED"); |
| } |
| |
| static int scale_check_pixel_exact(CT_Image src, CT_Image dst, int x, int y, vx_enum interpolation, vx_border_t border) |
| { |
| vx_uint8 res = *CT_IMAGE_DATA_PTR_8U(dst, x, y); |
| vx_float32 x_src = (((vx_float32)x + 0.5f) * (vx_float32)src->width / (vx_float32)dst->width) - 0.5f; |
| vx_float32 y_src = (((vx_float32)y + 0.5f) * (vx_float32)src->height / (vx_float32)dst->height) - 0.5f; |
| vx_float32 x_minf = floorf(x_src); |
| vx_float32 y_minf = floorf(y_src); |
| int x_min = (vx_int32)x_minf; |
| int y_min = (vx_int32)y_minf; |
| int x_ref = x_min; |
| int y_ref = y_min; |
| if (x_src - x_minf >= 0.5f) |
| x_ref++; |
| if (y_src - y_minf >= 0.5f) |
| y_ref++; |
| if (interpolation == VX_INTERPOLATION_NEAREST_NEIGHBOR) |
| { |
| vx_int32 ref = ct_image_get_pixel_8u(src, x_ref, y_ref, border); |
| if (ref == -1 || ref == res) |
| return 1; |
| CT_FAIL_(return 0, "Check failed for pixel (%d, %d): %d (expected %d)", x, y, (int)res, (int)ref); |
| } |
| if (interpolation == VX_INTERPOLATION_BILINEAR) |
| { |
| vx_float32 s = x_src - x_minf; |
| vx_float32 t = y_src - y_minf; |
| vx_int32 p00 = ct_image_get_pixel_8u(src, x_min + 0, y_min + 0, border); |
| vx_int32 p01 = ct_image_get_pixel_8u(src, x_min + 0, y_min + 1, border); |
| vx_int32 p10 = ct_image_get_pixel_8u(src, x_min + 1, y_min + 0, border); |
| vx_int32 p11 = ct_image_get_pixel_8u(src, x_min + 1, y_min + 1, border); |
| vx_float32 ref_float; |
| vx_int32 ref; |
| |
| // If the computed coordinate is very close to the boundary (1e-7), we don't |
| // consider it out-of-bound, in order to handle potential float accuracy errors |
| vx_bool defined = (vx_bool)((p00 != -1) && (p10 != -1) && (p01 != -1) && (p11 != -1)); |
| if (defined == vx_false_e) |
| { |
| vx_bool defined_any = (vx_bool)((p00 != -1) || (p10 != -1) || (p01 != -1) || (p11 != -1)); |
| if (defined_any) |
| { |
| if ((p00 == -1 || p10 == -1) && fabs(t - 1.0) <= 1e-7) |
| p00 = p10 = 0; |
| else if ((p01 == -1 || p11 == -1) && fabs(t - 0.0) <= 1e-7) |
| p01 = p11 = 0; |
| if ((p00 == -1 || p01 == -1) && fabs(s - 1.0) <= 1e-7) |
| p00 = p01 = 0; |
| else if ((p10 == -1 || p11 == -1) && fabs(s - 0.0) <= 1e-7) |
| p10 = p11 = 0; |
| defined = (vx_bool)((p00 != -1) && (p10 != -1) && (p01 != -1) && (p11 != -1)); |
| } |
| } |
| if (defined == vx_false_e) { |
| return 1; |
| } |
| |
| // Compute the expected result (float) |
| ref_float = (1 - s) * (1 - t) * p00 + |
| ( s) * (1 - t) * p10 + |
| (1 - s) * ( t) * p01 + |
| ( s) * ( t) * p11; |
| |
| // Take the nearest integer to avoid problems with casts in case of float rounding errors |
| // (e.g: 30.999999 should give 31, not 30) |
| ref = (vx_int32)(ref_float + 0.5f); |
| |
| // The result must be exact |
| if (ref == res) { |
| return 1; |
| } |
| |
| CT_FAIL_(return 0, "Check failed for pixel (%d, %d): %d (expected %d)", x, y, (int)res, (int)ref); |
| } |
| if (interpolation == VX_INTERPOLATION_AREA) |
| { |
| vx_int32 ref; |
| ASSERT_(return 0, dst->width % src->width == 0 && dst->height % src->height == 0); |
| ref = ct_image_get_pixel_8u(src, x_ref, y_ref, border); |
| if (ref == -1) |
| return 1; |
| if (ref == res) |
| return 1; |
| CT_FAIL_(return 0, "Check failed for pixel (%d, %d): %d (expected %d)", x, y, (int)res, (int)ref); |
| } |
| CT_FAIL_(return 0, "NOT IMPLEMENTED"); |
| } |
| |
| static void scale_validate(CT_Image src, CT_Image dst, vx_enum interpolation, vx_border_t border, int exact) |
| { |
| int num_failed = 0; |
| if (src->width == dst->width && src->height == dst->height) // special case for scale=1.0 |
| { |
| ASSERT_EQ_CTIMAGE(src, dst); |
| return; |
| } |
| CT_FILL_IMAGE_8U(, dst, |
| { |
| int check; |
| if (exact == 0) |
| ASSERT_NO_FAILURE(check = scale_check_pixel(src, dst, x, y, interpolation, border)); |
| else |
| ASSERT_NO_FAILURE(check = scale_check_pixel_exact(src, dst, x, y, interpolation, border)); |
| if (check == 0) { |
| num_failed++; |
| } |
| }); |
| if (interpolation == VX_INTERPOLATION_BILINEAR) |
| { |
| int total = dst->width * dst->height; |
| if (num_failed * 100 > total * 2) // 98% should be valid |
| { |
| CT_FAIL("Check failed: %g (%d) pixels are wrong", (float)num_failed / total, num_failed); |
| } |
| } |
| } |
| |
| static void scale_check(CT_Image src, CT_Image dst, vx_enum interpolation, vx_border_t border, int exact) |
| { |
| ASSERT(src && dst); |
| scale_validate(src, dst, interpolation, border, exact); |
| #if 0 |
| if (CT_HasFailure()) |
| { |
| printf("=== SRC ===\n"); |
| ct_dump_image_info_ex(src, 16, 8); |
| printf("=== DST ===\n"); |
| ct_dump_image_info_ex(dst, 16, 8); |
| } |
| #endif |
| } |
| |
| typedef struct { |
| const char* testName; |
| int dummy; |
| vx_enum interpolation; |
| CT_Image (*generator)(const char* fileName, int width, int height); |
| const char* fileName; |
| void (*dst_size_generator)(int width, int height, int* dst_width, int* dst_height); |
| int exact_result; |
| int width, height; |
| vx_border_t border; |
| } Arg; |
| |
| |
| void dst_size_generator_1_1(int width, int height, int* dst_width, int* dst_height) |
| { |
| *dst_width = width; |
| *dst_height = height; |
| } |
| |
| void dst_size_generator_1_2(int width, int height, int* dst_width, int* dst_height) |
| { |
| *dst_width = width * 2; |
| *dst_height = height * 2; |
| } |
| |
| void dst_size_generator_1_3(int width, int height, int* dst_width, int* dst_height) |
| { |
| *dst_width = width * 3; |
| *dst_height = height * 3; |
| } |
| |
| void dst_size_generator_2_1(int width, int height, int* dst_width, int* dst_height) |
| { |
| *dst_width = (width + 1) / 2; |
| *dst_height = (height + 1) / 2; |
| } |
| |
| void dst_size_generator_3_1(int width, int height, int* dst_width, int* dst_height) |
| { |
| *dst_width = (width + 2) / 3; |
| *dst_height = (height + 2) / 3; |
| } |
| |
| void dst_size_generator_4_1(int width, int height, int* dst_width, int* dst_height) |
| { |
| *dst_width = (width + 3) / 4; |
| *dst_height = (height + 3) / 4; |
| } |
| |
| void dst_size_generator_5_1(int width, int height, int* dst_width, int* dst_height) |
| { |
| *dst_width = (width + 4) / 5; |
| *dst_height = (height + 4) / 5; |
| } |
| |
| void dst_size_generator_SCALE_PYRAMID_ORB(int width, int height, int* dst_width, int* dst_height) |
| { |
| *dst_width = (int)(width * VX_SCALE_PYRAMID_ORB); |
| *dst_height = (int)(height * VX_SCALE_PYRAMID_ORB); |
| } |
| |
| void dst_size_generator_SCALE_NEAR_UP(int width, int height, int* dst_width, int* dst_height) |
| { |
| *dst_width = width + 1; |
| *dst_height = height + 1; |
| } |
| |
| void dst_size_generator_SCALE_NEAR_DOWN(int width, int height, int* dst_width, int* dst_height) |
| { |
| *dst_width = width - 1; |
| *dst_height = height - 1; |
| } |
| |
| #define STR_VX_INTERPOLATION_NEAREST_NEIGHBOR "NN" |
| #define STR_VX_INTERPOLATION_BILINEAR "BILINEAR" |
| #define STR_VX_INTERPOLATION_AREA "AREA" |
| |
| #define SCALE_TEST(interpolation, inputDataGenerator, inputDataFile, scale, exact, nextmacro, ...) \ |
| CT_EXPAND(nextmacro(STR_##interpolation "/" inputDataFile "/" #scale, __VA_ARGS__, \ |
| interpolation, inputDataGenerator, inputDataFile, dst_size_generator_ ## scale, exact)) |
| |
| #define ADD_DST_SIZE_NN(testArgName, nextmacro, ...) \ |
| CT_EXPAND(nextmacro(testArgName "/1_1", __VA_ARGS__, dst_size_generator_1_1)), \ |
| CT_EXPAND(nextmacro(testArgName "/1_2", __VA_ARGS__, dst_size_generator_1_2)), \ |
| CT_EXPAND(nextmacro(testArgName "/2_1", __VA_ARGS__, dst_size_generator_2_1)), \ |
| CT_EXPAND(nextmacro(testArgName "/3_1", __VA_ARGS__, dst_size_generator_3_1)), \ |
| CT_EXPAND(nextmacro(testArgName "/4_1", __VA_ARGS__, dst_size_generator_4_1)) |
| |
| #define ADD_DST_SIZE_BILINEAR(testArgName, nextmacro, ...) \ |
| CT_EXPAND(nextmacro(testArgName "/1:1", __VA_ARGS__, dst_size_generator_1_1)), \ |
| CT_EXPAND(nextmacro(testArgName "/1:2", __VA_ARGS__, dst_size_generator_1_2)), \ |
| CT_EXPAND(nextmacro(testArgName "/2:1", __VA_ARGS__, dst_size_generator_2_1)), \ |
| CT_EXPAND(nextmacro(testArgName "/3:1", __VA_ARGS__, dst_size_generator_3_1)), \ |
| CT_EXPAND(nextmacro(testArgName "/4:1", __VA_ARGS__, dst_size_generator_4_1)) |
| |
| #define ADD_DST_SIZE_AREA(testArgName, nextmacro, ...) \ |
| CT_EXPAND(nextmacro(testArgName "/1:1", __VA_ARGS__, dst_size_generator_1_1)), \ |
| CT_EXPAND(nextmacro(testArgName "/87:100", __VA_ARGS__, dst_size_generator_87_100)), \ |
| CT_EXPAND(nextmacro(testArgName "/4:1", __VA_ARGS__, dst_size_generator_4_1)) |
| |
| #define ADD_SIZE_96x96(testArgName, nextmacro, ...) \ |
| CT_EXPAND(nextmacro(testArgName "/sz=96x96", __VA_ARGS__, 96, 96)) |
| |
| #define ADD_SIZE_100x100(testArgName, nextmacro, ...) \ |
| CT_EXPAND(nextmacro(testArgName "/sz=100x100", __VA_ARGS__, 100, 100)) |
| |
| #define PARAMETERS \ |
| /* 1:1 scale */ \ |
| SCALE_TEST(VX_INTERPOLATION_NEAREST_NEIGHBOR, scale_generate_random, "random", 1_1, 1, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_BILINEAR, scale_generate_random, "random", 1_1, 1, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_AREA, scale_generate_random, "random", 1_1, 1, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| /* NN upscale with integer factor */ \ |
| SCALE_TEST(VX_INTERPOLATION_NEAREST_NEIGHBOR, scale_generate_random, "random", 1_2, 1, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_NEAREST_NEIGHBOR, scale_generate_random, "random", 1_3, 1, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_NEAREST_NEIGHBOR, scale_read_image, "lena.bmp", 1_2, 1, ADD_SIZE_NONE, ADD_VX_BORDERS, ARG, 0), \ |
| /* NN downscale with odd integer factor */\ |
| SCALE_TEST(VX_INTERPOLATION_NEAREST_NEIGHBOR, scale_generate_random, "random", 3_1, 1, ADD_SIZE_96x96, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_NEAREST_NEIGHBOR, scale_generate_random, "random", 5_1, 1, ADD_SIZE_100x100, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_NEAREST_NEIGHBOR, scale_generate_pattern3x3, "pattern3x3", 3_1, 1, ADD_SIZE_96x96, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_NEAREST_NEIGHBOR, scale_read_image, "lena.bmp", 3_1, 0, ADD_SIZE_NONE, ADD_VX_BORDERS, ARG, 0), \ |
| /* other NN downscales */ \ |
| SCALE_TEST(VX_INTERPOLATION_NEAREST_NEIGHBOR, scale_generate_random, "random", 2_1, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_NEAREST_NEIGHBOR, scale_generate_random, "random", 4_1, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_NEAREST_NEIGHBOR, scale_generate_random, "random", SCALE_PYRAMID_ORB, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| /* BILINEAR upscale with integer factor */ \ |
| SCALE_TEST(VX_INTERPOLATION_BILINEAR, scale_generate_random, "random", 1_2, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_BILINEAR, scale_generate_random, "random", 1_3, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| /* BILINEAR downscales */ \ |
| SCALE_TEST(VX_INTERPOLATION_BILINEAR, scale_generate_random, "random", 2_1, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_BILINEAR, scale_generate_random, "random", 3_1, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_BILINEAR, scale_generate_random, "random", 4_1, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_BILINEAR, scale_generate_random, "random", 5_1, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_BILINEAR, scale_generate_random, "random", SCALE_PYRAMID_ORB, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| /* AREA tests */ \ |
| SCALE_TEST(VX_INTERPOLATION_AREA, scale_generate_gradient_16x16, "gradient16x16", 4_1, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_AREA, scale_read_image, "lena.bmp", 4_1, 0, ADD_SIZE_NONE, ADD_VX_BORDERS, ARG, 0), \ |
| /* AREA upscale */ \ |
| SCALE_TEST(VX_INTERPOLATION_AREA, scale_generate_random, "random", 1_2, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_AREA, scale_generate_random, "random", 1_3, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| /* other */ \ |
| SCALE_TEST(VX_INTERPOLATION_NEAREST_NEIGHBOR, scale_generate_random, "random", SCALE_NEAR_UP, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_BILINEAR, scale_generate_random, "random", SCALE_NEAR_UP, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_AREA, scale_generate_random, "random", SCALE_NEAR_UP, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_NEAREST_NEIGHBOR, scale_generate_random, "random", SCALE_NEAR_DOWN, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_BILINEAR, scale_generate_random, "random", SCALE_NEAR_DOWN, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| SCALE_TEST(VX_INTERPOLATION_AREA, scale_generate_random, "random", SCALE_NEAR_DOWN, 0, ADD_SIZE_SMALL_SET, ADD_VX_BORDERS, ARG, 0), \ |
| |
| TEST_WITH_ARG(Scale, testGraphProcessing, Arg, |
| PARAMETERS |
| ) |
| { |
| vx_context context = context_->vx_context_; |
| int dst_width = 0, dst_height = 0; |
| vx_image src_image = 0, dst_image = 0; |
| vx_graph graph = 0; |
| vx_node node = 0; |
| |
| CT_Image src = NULL, dst = NULL; |
| |
| ASSERT_NO_FAILURE(src = arg_->generator(arg_->fileName, arg_->width, arg_->height)); |
| ASSERT_VX_OBJECT(src_image = ct_image_to_vx_image(src, context), VX_TYPE_IMAGE); |
| |
| ASSERT_NO_FAILURE(arg_->dst_size_generator(src->width, src->height, &dst_width, &dst_height)); |
| |
| ASSERT_VX_OBJECT(dst_image = vxCreateImage(context, dst_width, dst_height, VX_DF_IMAGE_U8), VX_TYPE_IMAGE); |
| |
| ASSERT_VX_OBJECT(graph = vxCreateGraph(context), VX_TYPE_GRAPH); |
| |
| ASSERT_VX_OBJECT(node = vxScaleImageNode(graph, src_image, dst_image, arg_->interpolation), VX_TYPE_NODE); |
| |
| VX_CALL(vxSetNodeAttribute(node, VX_NODE_BORDER, &arg_->border, sizeof(arg_->border))); |
| |
| VX_CALL(vxVerifyGraph(graph)); |
| VX_CALL(vxProcessGraph(graph)); |
| |
| ASSERT_NO_FAILURE(dst = ct_image_from_vx_image(dst_image)); |
| |
| ASSERT_NO_FAILURE(scale_check(src, dst, arg_->interpolation, arg_->border, arg_->exact_result)); |
| |
| VX_CALL(vxReleaseNode(&node)); |
| VX_CALL(vxReleaseGraph(&graph)); |
| |
| ASSERT(node == 0); |
| ASSERT(graph == 0); |
| |
| VX_CALL(vxReleaseImage(&dst_image)); |
| VX_CALL(vxReleaseImage(&src_image)); |
| |
| ASSERT(dst_image == 0); |
| ASSERT(src_image == 0); |
| } |
| |
| TEST_WITH_ARG(Scale, testImmediateProcessing, Arg, |
| PARAMETERS |
| ) |
| { |
| vx_context context = context_->vx_context_; |
| int dst_width = 0, dst_height = 0; |
| vx_image src_image = 0, dst_image = 0; |
| |
| CT_Image src = NULL, dst = NULL; |
| |
| ASSERT_NO_FAILURE(src = arg_->generator(arg_->fileName, arg_->width, arg_->height)); |
| ASSERT_VX_OBJECT(src_image = ct_image_to_vx_image(src, context), VX_TYPE_IMAGE); |
| |
| ASSERT_NO_FAILURE(arg_->dst_size_generator(src->width, src->height, &dst_width, &dst_height)); |
| |
| ASSERT_VX_OBJECT(dst_image = vxCreateImage(context, dst_width, dst_height, VX_DF_IMAGE_U8), VX_TYPE_IMAGE); |
| |
| VX_CALL(vxSetContextAttribute(context, VX_CONTEXT_IMMEDIATE_BORDER, &arg_->border, sizeof(arg_->border))); |
| |
| VX_CALL(vxuScaleImage(context, src_image, dst_image, arg_->interpolation)); |
| |
| ASSERT_NO_FAILURE(dst = ct_image_from_vx_image(dst_image)); |
| |
| ASSERT_NO_FAILURE(scale_check(src, dst, arg_->interpolation, arg_->border, arg_->exact_result)); |
| |
| VX_CALL(vxReleaseImage(&dst_image)); |
| VX_CALL(vxReleaseImage(&src_image)); |
| |
| ASSERT(dst_image == 0); |
| ASSERT(src_image == 0); |
| } |
| |
| TESTCASE_TESTS(Scale, testNodeCreation, testGraphProcessing, testImmediateProcessing) |