Made image_create format aware (#594)

* Made image_create stride aware
This commit is contained in:
Brent Allen 2019-08-05 15:33:58 -07:00 коммит произвёл GitHub
Родитель 85cd9e2b0b
Коммит 0f82028001
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 227 добавлений и 41 удалений

Просмотреть файл

@ -604,7 +604,9 @@ K4A_EXPORT float k4a_capture_get_temperature_c(k4a_capture_t capture_handle);
* compressed formats that may not be represented by the same number of bytes per line.
*
* \remarks
* The function will allocate an image buffer of size \p height_pixels * \p stride_bytes.
* For most image formats, the function will allocate an image buffer of size \p height_pixels * \p stride_bytes.
* Buffers #K4A_IMAGE_FORMAT_COLOR_NV12 format will allocate an additional \p height_pixels / 2 set of lines (each of \p
* stride_bytes). This function cannot be used to allocate #K4A_IMAGE_FORMAT_COLOR_MJPG buffers.
*
* \remarks
* To create an image object without the API allocating memory, or to represent an image that has a non-deterministic

Просмотреть файл

@ -171,10 +171,140 @@ k4a_result_t image_create(k4a_image_format_t format,
image_context_t *image = NULL;
k4a_result_t result;
size_t size = (size_t)height_pixels * (size_t)stride_bytes;
size_t size = 0;
*image_handle = NULL;
result = TRACE_CALL(image_create_empty_image(source, size, image_handle));
switch (format)
{
case K4A_IMAGE_FORMAT_COLOR_MJPG:
{
LOG_ERROR("K4A_IMAGE_FORMAT_COLOR_MJPG does not have a constant stride. Buffer size cannot be calculated.", 0);
result = K4A_RESULT_FAILED;
break;
}
case K4A_IMAGE_FORMAT_COLOR_NV12:
{
if (height_pixels % 2 != 0)
{
LOG_ERROR("NV12 requires an even number of lines. Height %d is invalid.", height_pixels);
result = K4A_RESULT_FAILED;
}
else if (width_pixels % 2 != 0)
{
LOG_ERROR("NV12 requires an even number of pixels per line. Width of %d is invalid.", width_pixels);
result = K4A_RESULT_FAILED;
}
else if (stride_bytes < 1 * width_pixels)
{
LOG_ERROR("Insufficient stride (%d bytes) to represent image width (%d pixels).",
stride_bytes,
width_pixels);
result = K4A_RESULT_FAILED;
}
else
{
// Calculate correct size for NV12 (extra color lines follow Y samples)
size = 3 * (size_t)height_pixels * (size_t)stride_bytes / 2;
result = K4A_RESULT_SUCCEEDED;
}
break;
}
// 1 Byte per pixel
case K4A_IMAGE_FORMAT_CUSTOM8:
{
if (stride_bytes < 1 * width_pixels)
{
LOG_ERROR("Insufficient stride (%d bytes) to represent image width (%d pixels).",
stride_bytes,
width_pixels);
result = K4A_RESULT_FAILED;
}
else
{
size = (size_t)height_pixels * (size_t)stride_bytes;
result = K4A_RESULT_SUCCEEDED;
}
break;
}
// 2 Bytes per pixel
case K4A_IMAGE_FORMAT_DEPTH16:
case K4A_IMAGE_FORMAT_IR16:
case K4A_IMAGE_FORMAT_CUSTOM16:
{
if (stride_bytes < 2 * width_pixels)
{
LOG_ERROR("Insufficient stride (%d bytes) to represent image width (%d pixels).",
stride_bytes,
width_pixels);
result = K4A_RESULT_FAILED;
}
else
{
size = (size_t)height_pixels * (size_t)stride_bytes;
result = K4A_RESULT_SUCCEEDED;
}
break;
}
// 2 Bytes per pixel
case K4A_IMAGE_FORMAT_COLOR_YUY2:
{
if (width_pixels % 2 != 0)
{
LOG_ERROR("YUY2 requires an even number of pixels per line. Width of %d is invalid.", width_pixels);
result = K4A_RESULT_FAILED;
}
else if (stride_bytes < 2 * width_pixels)
{
LOG_ERROR("Insufficient stride (%d bytes) to represent image width (%d pixels).",
stride_bytes,
width_pixels);
result = K4A_RESULT_FAILED;
}
else
{
size = (size_t)height_pixels * (size_t)stride_bytes;
result = K4A_RESULT_SUCCEEDED;
}
break;
}
// 4 Bytes per pixel
case K4A_IMAGE_FORMAT_COLOR_BGRA32:
{
if (stride_bytes < 4 * width_pixels)
{
LOG_ERROR("Insufficient stride (%d bytes) to represent image width (%d pixels).",
stride_bytes,
width_pixels);
result = K4A_RESULT_FAILED;
}
else
{
size = (size_t)height_pixels * (size_t)stride_bytes;
result = K4A_RESULT_SUCCEEDED;
}
break;
}
// Unknown
case K4A_IMAGE_FORMAT_CUSTOM:
default:
{
size = (size_t)height_pixels * (size_t)stride_bytes;
result = K4A_RESULT_SUCCEEDED;
break;
}
}
if (K4A_SUCCEEDED(result))
{
result = TRACE_CALL(image_create_empty_image(source, size, image_handle));
}
if (K4A_SUCCEEDED(result))
{
@ -188,7 +318,7 @@ k4a_result_t image_create(k4a_image_format_t format,
image->stride_bytes = stride_bytes;
}
if (K4A_FAILED(result) && image_handle)
if (K4A_FAILED(result) && *image_handle)
{
image_dec_ref(*image_handle);
*image_handle = NULL;

Просмотреть файл

@ -181,54 +181,108 @@ TEST(allocator_ut, image_api_validation)
{
// Unsupported formats for this creation API.
// Invalid FORMAT
k4a_image_format_t bad_format = (k4a_image_format_t)99;
ASSERT_EQ(K4A_RESULT_FAILED, image_create(bad_format, 10, 10, 1, ALLOCATION_SOURCE_USER, &image));
// No output argument
ASSERT_EQ(K4A_RESULT_FAILED,
image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 10, 10, 1, ALLOCATION_SOURCE_USER, NULL));
// Stride of zero
ASSERT_EQ(K4A_RESULT_FAILED,
image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 10, 10, 0, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(K4A_RESULT_FAILED,
image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 10, 10, 0, ALLOCATION_SOURCE_USER, NULL));
ASSERT_EQ(K4A_RESULT_FAILED,
image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 10, 0, 1, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 10, 0, 1, ALLOCATION_SOURCE_USER, NULL));
ASSERT_EQ(K4A_RESULT_FAILED,
image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 10, 0, 0, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 10, 0, 0, ALLOCATION_SOURCE_USER, NULL));
ASSERT_EQ(K4A_RESULT_FAILED,
image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 0, 10, 1, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 0, 10, 1, ALLOCATION_SOURCE_USER, NULL));
ASSERT_EQ(K4A_RESULT_FAILED,
image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 0, 10, 0, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 0, 10, 0, ALLOCATION_SOURCE_USER, NULL));
ASSERT_EQ(K4A_RESULT_FAILED,
image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 0, 0, 1, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 0, 0, 1, ALLOCATION_SOURCE_USER, NULL));
ASSERT_EQ(K4A_RESULT_FAILED,
image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 0, 0, 0, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 0, 0, 0, ALLOCATION_SOURCE_USER, NULL));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(bad_format, 10, 10, 1, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(bad_format, 10, 10, 1, ALLOCATION_SOURCE_USER, NULL));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(bad_format, 10, 10, 0, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(bad_format, 10, 10, 0, ALLOCATION_SOURCE_USER, NULL));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(bad_format, 10, 0, 1, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(bad_format, 10, 0, 1, ALLOCATION_SOURCE_USER, NULL));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(bad_format, 10, 0, 0, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(bad_format, 10, 0, 0, ALLOCATION_SOURCE_USER, NULL));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(bad_format, 0, 10, 1, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(bad_format, 0, 10, 1, ALLOCATION_SOURCE_USER, NULL));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(bad_format, 0, 10, 0, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(bad_format, 0, 10, 0, ALLOCATION_SOURCE_USER, NULL));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(bad_format, 0, 0, 1, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(bad_format, 0, 0, 1, ALLOCATION_SOURCE_USER, NULL));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(bad_format, 0, 0, 0, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(K4A_RESULT_FAILED, image_create(bad_format, 0, 0, 0, ALLOCATION_SOURCE_USER, NULL));
// Stride length
// Validate a valid length and an invalid length
// NV12
// Minimum stride
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 10, 10, 1, ALLOCATION_SOURCE_USER, &image));
image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 10, 10, 10, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(10 * 10 * 3 / 2, (int)image_get_size(image));
image_dec_ref(image);
// Extra stride
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 10, 10, 11, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(10 * 11 * 3 / 2, (int)image_get_size(image));
image_dec_ref(image);
// Insufficient stride
ASSERT_EQ(K4A_RESULT_FAILED,
image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 10, 10, 9, ALLOCATION_SOURCE_USER, &image));
// Odd number of rows
ASSERT_EQ(K4A_RESULT_FAILED,
image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 10, 11, 20, ALLOCATION_SOURCE_USER, &image));
// Odd number of columns
ASSERT_EQ(K4A_RESULT_FAILED,
image_create(K4A_IMAGE_FORMAT_COLOR_NV12, 11, 10, 20, ALLOCATION_SOURCE_USER, &image));
// YUY2
// Minimum stride
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
image_create(K4A_IMAGE_FORMAT_COLOR_YUY2, 10, 10, 20, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(/* lines * stride*/ 10 * 20, (int)image_get_size(image));
image_dec_ref(image);
// Extra stride
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
image_create(K4A_IMAGE_FORMAT_COLOR_YUY2, 10, 10, 22, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(/* lines * stride*/ 10 * 22, (int)image_get_size(image));
image_dec_ref(image);
// Insufficient stride
ASSERT_EQ(K4A_RESULT_FAILED,
image_create(K4A_IMAGE_FORMAT_COLOR_YUY2, 10, 10, 19, ALLOCATION_SOURCE_USER, &image));
// Odd number of rows
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
image_create(K4A_IMAGE_FORMAT_COLOR_YUY2, 10, 11, 20, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(/* lines * stride*/ 11 * 20, (int)image_get_size(image));
image_dec_ref(image);
// Odd number of columns
ASSERT_EQ(K4A_RESULT_FAILED,
image_create(K4A_IMAGE_FORMAT_COLOR_YUY2, 11, 10, 20, ALLOCATION_SOURCE_USER, &image));
// BGRA32
// Minimum stride
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
image_create(K4A_IMAGE_FORMAT_COLOR_BGRA32, 10, 10, 40, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(/* lines * stride*/ 10 * 40, (int)image_get_size(image));
image_dec_ref(image);
// Insufficient stride
ASSERT_EQ(K4A_RESULT_FAILED,
image_create(K4A_IMAGE_FORMAT_COLOR_BGRA32, 10, 10, 39, ALLOCATION_SOURCE_USER, &image));
// MJPEG (no length is valid)
ASSERT_EQ(K4A_RESULT_FAILED,
image_create(K4A_IMAGE_FORMAT_COLOR_MJPG, 10, 10, 100, ALLOCATION_SOURCE_USER, &image));
// DEPTH16
// Minimum stride
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
image_create(K4A_IMAGE_FORMAT_DEPTH16, 10, 10, 20, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(10 * 10 * 2, (int)image_get_size(image));
image_dec_ref(image);
// Insufficient stride
ASSERT_EQ(K4A_RESULT_FAILED,
image_create(K4A_IMAGE_FORMAT_DEPTH16, 10, 10, 19, ALLOCATION_SOURCE_USER, &image));
// Custom8
// Minimum stride
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
image_create(K4A_IMAGE_FORMAT_CUSTOM8, 10, 10, 10, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(10 * 10, (int)image_get_size(image));
image_dec_ref(image);
// Insufficient stride
ASSERT_EQ(K4A_RESULT_FAILED,
(int)image_create(K4A_IMAGE_FORMAT_CUSTOM8, 10, 10, 9, ALLOCATION_SOURCE_USER, &image));
// Height of zero
ASSERT_EQ(K4A_RESULT_FAILED,
(int)image_create(K4A_IMAGE_FORMAT_CUSTOM8, 10, 0, 10, ALLOCATION_SOURCE_USER, &image));
// Width of zero
ASSERT_EQ(K4A_RESULT_FAILED,
(int)image_create(K4A_IMAGE_FORMAT_CUSTOM8, 0, 10, 10, ALLOCATION_SOURCE_USER, &image));
ASSERT_EQ(allocator_test_for_leaks(), 0);
}