windowscodecs/tests: Add tests for decoding BC1 format.

Signed-off-by: Ziqing Hui <zhui@codeweavers.com>
Signed-off-by: Esme Povirk <esme@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Ziqing Hui 2020-08-17 10:24:13 +08:00 committed by Alexandre Julliard
parent f178907850
commit 6b5579b65f
1 changed files with 104 additions and 0 deletions

View File

@ -24,6 +24,12 @@
#include "wincodec.h"
#include "wine/test.h"
#define GET_RGB565_R(color) ((BYTE)(((color) >> 11) & 0x1F))
#define GET_RGB565_G(color) ((BYTE)(((color) >> 5) & 0x3F))
#define GET_RGB565_B(color) ((BYTE)(((color) >> 0) & 0x1F))
#define MAKE_RGB565(r, g, b) ((WORD)(((BYTE)(r) << 11) | ((BYTE)(g) << 5) | (BYTE)(b)))
#define MAKE_ARGB(a, r, g, b) (((DWORD)(a) << 24) | ((DWORD)(r) << 16) | ((DWORD)(g) << 8) | (DWORD)(b))
/* 1x1 uncompressed(Alpha) DDS image */
static BYTE test_dds_alpha[] = {
'D', 'D', 'S', ' ', 0x7C, 0x00, 0x00, 0x00, 0x07, 0x10, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,
@ -529,6 +535,81 @@ end:
return bpp;
}
static DWORD rgb565_to_argb(WORD color, BOOL has_alpha)
{
return (has_alpha && !color) ? 0: MAKE_ARGB(0xFF, (GET_RGB565_R(color) * 0xFF + 0x0F) / 0x1F,
(GET_RGB565_G(color) * 0xFF + 0x1F) / 0x3F,
(GET_RGB565_B(color) * 0xFF + 0x0F) / 0x1F);
}
static void decode_bc1(const BYTE *blocks, UINT block_count, UINT width, UINT height, DWORD *buffer)
{
static const UINT BLOCK_SIZE = 8;
UINT stride = (width + 3) / 4 * 4;
int i, j, color_index, pixel_index = 0;
const BYTE *block, *color_indices;
DWORD *pixel = buffer;
BOOL has_alpha;
WORD color[4];
for (i = 0; i < block_count; i++)
{
block = blocks + i * BLOCK_SIZE;
color[0] = *((WORD *)block);
color[1] = *((WORD *)block + 1);
has_alpha = color[0] <= color[1];
if (has_alpha) {
color[2] = MAKE_RGB565(((GET_RGB565_R(color[0]) + GET_RGB565_R(color[1]) + 1) / 2),
((GET_RGB565_G(color[0]) + GET_RGB565_G(color[1]) + 1) / 2),
((GET_RGB565_B(color[0]) + GET_RGB565_B(color[1]) + 1) / 2));
color[3] = 0;
} else {
color[2] = MAKE_RGB565(((GET_RGB565_R(color[0]) * 2 + GET_RGB565_R(color[1]) + 1) / 3),
((GET_RGB565_G(color[0]) * 2 + GET_RGB565_G(color[1]) + 1) / 3),
((GET_RGB565_B(color[0]) * 2 + GET_RGB565_B(color[1]) + 1) / 3));
color[3] = MAKE_RGB565(((GET_RGB565_R(color[0]) + GET_RGB565_R(color[1]) * 2 + 1) / 3),
((GET_RGB565_G(color[0]) + GET_RGB565_G(color[1]) * 2 + 1) / 3),
((GET_RGB565_B(color[0]) + GET_RGB565_B(color[1]) * 2 + 1) / 3));
}
color_indices = blocks + 4;
for (j = 0; j < 16; j++, pixel_index++)
{
if ((pixel_index % stride >= width) ||
(pixel_index / stride >= height)) continue;
color_index = (color_indices[j / 4] >> ((j % 4) * 2)) & 0x3;
*pixel = rgb565_to_argb(color[color_index], has_alpha);
pixel++;
}
}
}
static BOOL color_match(DWORD color_a, DWORD color_b)
{
static const int tolerance = 8;
const int da = abs((int)((color_a & 0xFF000000) >> 24) - (int)((color_b & 0xFF000000) >> 24));
const int dr = abs((int)((color_a & 0x00FF0000) >> 16) - (int)((color_b & 0x00FF0000) >> 16));
const int dg = abs((int)((color_a & 0x0000FF00) >> 8) - (int)((color_b & 0x0000FF00) >> 8));
const int db = abs((int)((color_a & 0x000000FF) >> 0) - (int)((color_b & 0x000000FF) >> 0));
return (da <= tolerance && dr <= tolerance && dg <= tolerance && db <= tolerance);
}
static BOOL color_buffer_match(DWORD *color_buffer_a, DWORD *color_buffer_b, UINT color_count)
{
UINT i;
for (i = 0; i < color_count; i++)
{
if (!color_match(color_buffer_a[i], color_buffer_b[i])) return FALSE;
}
return TRUE;
}
static void test_dds_decoder_initialize(void)
{
int i;
@ -799,6 +880,7 @@ static void test_dds_decoder_frame_data(IWICBitmapFrameDecode* frame, IWICDdsFra
WICRect rect = { 0, 0, 1, 1 }, rect_test_a = { 0, 0, 0, 0 }, rect_test_b = { 0, 0, 0xdeadbeaf, 0xdeadbeaf };
WICRect rect_test_c = { -0xdeadbeaf, -0xdeadbeaf, 1, 1 }, rect_test_d = { 0xdeadbeaf, 0xdeadbeaf, 1, 1 };
BYTE buffer[2048];
DWORD pixels[2048];
UINT stride, frame_stride, frame_size, frame_width, frame_height, width_in_blocks, height_in_blocks, bpp;
UINT width, height, depth, array_index;
UINT block_offset;
@ -909,6 +991,7 @@ static void test_dds_decoder_frame_data(IWICBitmapFrameDecode* frame, IWICDdsFra
bpp = get_pixel_format_bpp(&pixel_format);
stride = rect.Width * bpp / 8;
frame_stride = frame_width * bpp / 8;
frame_size = frame_stride * frame_height;
hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, 0, 0, NULL);
ok(hr == E_INVALIDARG, "Test %u, frame %u: CopyPixels got unexpected hr %#x\n", i, frame_index, hr);
@ -952,6 +1035,27 @@ static void test_dds_decoder_frame_data(IWICBitmapFrameDecode* frame, IWICDdsFra
hr = IWICBitmapFrameDecode_CopyPixels(frame, &rect, stride, sizeof(buffer), NULL);
ok(hr == E_INVALIDARG, "Test %u, frame %u: CopyBlocks got unexpected hr %#x\n", i, frame_index, hr);
if (format_info.DxgiFormat == DXGI_FORMAT_BC1_UNORM) {
decode_bc1(test_data[i].data + block_offset, width_in_blocks * height_in_blocks, frame_width, frame_height, pixels);
hr = IWICBitmapFrameDecode_CopyPixels(frame, &rect, stride, sizeof(buffer), buffer);
ok(hr == S_OK, "Test %u, frame %u: CopyPixels failed, hr %#x\n", i, frame_index, hr);
if (hr == S_OK) {
todo_wine
ok(color_buffer_match((DWORD *)pixels, (DWORD *)buffer, 1),
"Test %u, frame %u: Pixels mismatch\n", i, frame_index);
}
hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, frame_stride, sizeof(buffer), buffer);
ok(hr == S_OK, "Test %u, frame %u: CopyPixels failed, hr %#x\n", i, frame_index, hr);
if (hr == S_OK) {
todo_wine
ok(color_buffer_match((DWORD *)pixels, (DWORD *)buffer, frame_size / (bpp / 8)),
"Test %u, frame %u: Pixels mismatch\n", i, frame_index);
}
}
}
static void test_dds_decoder_frame(IWICBitmapDecoder *decoder, int i)