diff --git a/dlls/windowscodecs/ddsformat.c b/dlls/windowscodecs/ddsformat.c index 9f6aab4e914..12b6c42f64a 100644 --- a/dlls/windowscodecs/ddsformat.c +++ b/dlls/windowscodecs/ddsformat.c @@ -589,9 +589,36 @@ static HRESULT WINAPI DdsFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface, static HRESULT WINAPI DdsFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface, const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer) { - FIXME("(%p,%s,%u,%u,%p): stub.\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer); + DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface); + UINT bpp, frame_stride, frame_size; + INT x, y, width, height; - return E_NOTIMPL; + TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer); + + if (!pbBuffer) return E_INVALIDARG; + + bpp = This->info.pixel_format_bpp; + frame_stride = This->info.width * bpp / 8; + frame_size = frame_stride * This->info.height; + if (!prc) { + if (cbStride < frame_stride) return E_INVALIDARG; + if (cbBufferSize < frame_size) return WINCODEC_ERR_INSUFFICIENTBUFFER; + return S_OK; + } + + x = prc->X; + y = prc->Y; + width = prc->Width; + height = prc->Height; + if (x < 0 || y < 0 || width <= 0 || height <= 0 || + x + width > This->info.width || + y + height > This->info.height) { + return E_INVALIDARG; + } + if (cbStride < width * bpp / 8) return E_INVALIDARG; + if (cbBufferSize < cbStride * height) return WINCODEC_ERR_INSUFFICIENTBUFFER; + + return S_OK; } static HRESULT WINAPI DdsFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface, diff --git a/dlls/windowscodecs/tests/ddsformat.c b/dlls/windowscodecs/tests/ddsformat.c index 49de7e566ed..2d5afa8e6ed 100644 --- a/dlls/windowscodecs/tests/ddsformat.c +++ b/dlls/windowscodecs/tests/ddsformat.c @@ -506,6 +506,29 @@ static BOOL has_extended_header(const BYTE *data) return data[84] == 'D' && data[85] == 'X' && data[86] == '1' && data[87] == '0'; } +static UINT get_pixel_format_bpp(GUID *pixel_format) +{ + HRESULT hr; + UINT bpp = 0; + IWICComponentInfo *info = NULL; + IWICPixelFormatInfo* format_info = NULL; + + hr = IWICImagingFactory_CreateComponentInfo(factory, pixel_format, &info); + ok(hr == S_OK, "CreateComponentInfo failed, hr %#x\n", hr); + if (hr != S_OK) goto end; + hr = IWICComponentInfo_QueryInterface(info, &IID_IWICPixelFormatInfo, (void **)&format_info); + ok(hr == S_OK, "QueryInterface failed, hr %#x\n", hr); + if (hr != S_OK) goto end; + hr = IWICPixelFormatInfo_GetBitsPerPixel(format_info, &bpp); + ok(hr == S_OK, "GetBitsPerPixel failed, hr %#x\n", hr); + +end: + if (format_info) IWICPixelFormatInfo_Release(format_info); + if (info) IWICComponentInfo_Release(info); + + return bpp; +} + static void test_dds_decoder_initialize(void) { int i; @@ -767,19 +790,26 @@ static void test_dds_decoder_frame_properties(IWICBitmapFrameDecode *frame_decod i, frame_index, debugstr_guid(test_data[i].expected_pixel_format), debugstr_guid(&pixel_format)); } -static void test_dds_decoder_frame_data(IWICDdsFrameDecode *dds_frame, UINT frame_count, WICDdsParameters *params, - int i, int frame_index) +static void test_dds_decoder_frame_data(IWICBitmapFrameDecode* frame, IWICDdsFrameDecode *dds_frame, UINT frame_count, + WICDdsParameters *params, int i, int frame_index) { HRESULT hr; + GUID pixel_format; WICDdsFormatInfo format_info; 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[256]; - UINT stride, frame_stride, frame_size, width_in_blocks, height_in_blocks; + BYTE buffer[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; int slice_index; + hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &pixel_format); + ok(hr == S_OK, "Test %u, frame %u: GetPixelFormat failed, hr %#x\n", i, frame_index, hr); + if (hr != S_OK) return; + hr = IWICBitmapFrameDecode_GetSize(frame, &frame_width, &frame_height); + ok(hr == S_OK, "Test %u, frame %u: GetSize failed, hr %#x\n", i, frame_index, hr); + if (hr != S_OK) return; hr = IWICDdsFrameDecode_GetFormatInfo(dds_frame, &format_info); ok(hr == S_OK, "Test %u, frame %u: GetFormatInfo failed, hr %#x\n", i, frame_index, hr); if (hr != S_OK) return; @@ -790,6 +820,8 @@ static void test_dds_decoder_frame_data(IWICDdsFrameDecode *dds_frame, UINT fram frame_stride = width_in_blocks * format_info.BytesPerBlock; frame_size = frame_stride * height_in_blocks; + /* CopyBlocks tests */ + hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, 0, 0, NULL); ok(hr == E_INVALIDARG, "Test %u, frame %u: CopyBlocks got unexpected hr %#x\n", i, frame_index, hr); @@ -871,6 +903,55 @@ static void test_dds_decoder_frame_data(IWICDdsFrameDecode *dds_frame, UINT fram if (hr != S_OK) return; ok(!strncmp((const char *)test_data[i].data + block_offset, (const char *)buffer, frame_size), "Test %u, frame %u: Block data mismatch\n", i, frame_index); + + /* CopyPixels tests */ + + bpp = get_pixel_format_bpp(&pixel_format); + stride = rect.Width * bpp / 8; + frame_stride = frame_width * bpp / 8; + + 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); + + hr = IWICBitmapFrameDecode_CopyPixels(frame, &rect_test_a, stride, sizeof(buffer), buffer); + ok(hr == E_INVALIDARG, "Test %u, frame %u: CopyPixels got unexpected hr %#x\n", i, frame_index, hr); + hr = IWICBitmapFrameDecode_CopyPixels(frame, &rect_test_b, stride, sizeof(buffer), buffer); + ok(hr == E_INVALIDARG, "Test %u, frame %u: CopyPixels got unexpected hr %#x\n", i, frame_index, hr); + hr = IWICBitmapFrameDecode_CopyPixels(frame, &rect_test_c, stride, sizeof(buffer), buffer); + ok(hr == E_INVALIDARG, "Test %u, frame %u: CopyPixels got unexpected hr %#x\n", i, frame_index, hr); + hr = IWICBitmapFrameDecode_CopyPixels(frame, &rect_test_d, stride, sizeof(buffer), buffer); + ok(hr == E_INVALIDARG, "Test %u, frame %u: CopyPixels got unexpected hr %#x\n", i, frame_index, hr); + + hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, frame_stride - 1, sizeof(buffer), buffer); + ok(hr == E_INVALIDARG, "Test %u, frame %u: CopyPixels got unexpected hr %#x\n", i, frame_index, hr); + hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, frame_stride * 2, sizeof(buffer), buffer); + ok(hr == S_OK, "Test %u, frame %u: CopyPixels got unexpected hr %#x\n", i, frame_index, hr); + hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, frame_stride, sizeof(buffer), buffer); + ok(hr == S_OK, "Test %u, frame %u: CopyPixels got unexpected hr %#x\n", i, frame_index, hr); + hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, frame_stride, frame_stride * frame_height - 1, buffer); + ok(hr == WINCODEC_ERR_INSUFFICIENTBUFFER, "Test %u, frame %u: CopyPixels got unexpected hr %#x\n", i, frame_index, hr); + hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, frame_stride, frame_stride * frame_height, buffer); + ok(hr == S_OK, "Test %u, frame %u: CopyPixels got unexpected hr %#x\n", i, frame_index, hr); + + hr = IWICBitmapFrameDecode_CopyPixels(frame, &rect, 0, sizeof(buffer), buffer); + ok(hr == E_INVALIDARG, "Test %u, frame %u: CopyPixels got unexpected hr %#x\n", i, frame_index, hr); + hr = IWICBitmapFrameDecode_CopyPixels(frame, &rect, stride - 1, sizeof(buffer), buffer); + ok(hr == E_INVALIDARG, "Test %u, frame %u: CopyPixels got unexpected hr %#x\n", i, frame_index, hr); + hr = IWICBitmapFrameDecode_CopyPixels(frame, &rect, stride * 2, sizeof(buffer), buffer); + ok(hr == S_OK, "Test %u, frame %u: CopyPixels got unexpected hr %#x\n", i, frame_index, hr); + + hr = IWICBitmapFrameDecode_CopyPixels(frame, &rect, stride, 0, buffer); + ok(hr == WINCODEC_ERR_INSUFFICIENTBUFFER, "Test %u, frame %u: CopyPixels got unexpected hr %#x\n", i, frame_index, hr); + hr = IWICBitmapFrameDecode_CopyPixels(frame, &rect, stride, 1, buffer); + ok(hr == WINCODEC_ERR_INSUFFICIENTBUFFER || (hr == S_OK && test_data[i].expected_bytes_per_block == 1), + "Test %u, frame %u: CopyPixels got unexpected hr %#x\n", i, frame_index, hr); + hr = IWICBitmapFrameDecode_CopyPixels(frame, &rect, stride, stride * rect.Height - 1, buffer); + ok(hr == WINCODEC_ERR_INSUFFICIENTBUFFER, "Test %u, frame %u: CopyPixels got unexpected hr %#x\n", i, frame_index, hr); + hr = IWICBitmapFrameDecode_CopyPixels(frame, &rect, stride, stride * rect.Height, buffer); + ok(hr == S_OK, "Test %u, frame %u: CopyPixels got unexpected hr %#x\n", i, frame_index, hr); + + 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); } static void test_dds_decoder_frame(IWICBitmapDecoder *decoder, int i) @@ -905,7 +986,7 @@ static void test_dds_decoder_frame(IWICBitmapDecoder *decoder, int i) if (hr != S_OK) goto next; test_dds_decoder_frame_properties(frame_decode, dds_frame, frame_count, ¶ms, i, j); - test_dds_decoder_frame_data(dds_frame, frame_count, ¶ms, i, j); + test_dds_decoder_frame_data(frame_decode, dds_frame, frame_count, ¶ms, i, j); next: if (frame_decode) IWICBitmapFrameDecode_Release(frame_decode);