msvfw32-ICGetDisplayFormat: Added various fixes for stride handling.

This commit is contained in:
Sebastian Lackner
2016-04-04 23:12:57 +02:00
parent fb87fbb11d
commit f427133a03
7 changed files with 438 additions and 20 deletions

View File

@@ -0,0 +1,146 @@
From 6c25d94295130d7ab3e07dd985311520d303aad2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sun, 3 Apr 2016 17:47:43 +0200
Subject: msvfw32: Take stride into account and ask for palette in
ICGetDisplayFormat.
---
dlls/msvfw32/msvideo_main.c | 15 ++++++++++++---
dlls/msvfw32/tests/msvfw.c | 45 ++++++++++++++++++++++++++++++++++++++-------
2 files changed, 50 insertions(+), 10 deletions(-)
diff --git a/dlls/msvfw32/msvideo_main.c b/dlls/msvfw32/msvideo_main.c
index 6f91859..e3a7719 100644
--- a/dlls/msvfw32/msvideo_main.c
+++ b/dlls/msvfw32/msvideo_main.c
@@ -98,6 +98,11 @@ static const char *wine_dbgstr_icerr( int ret )
return str;
}
+static inline int get_stride(int width, int depth)
+{
+ return ((depth * width + 31) >> 3) & ~3;
+}
+
static WINE_HIC* MSVIDEO_FirstHic /* = NULL */;
typedef struct _reg_driver reg_driver;
@@ -770,23 +775,27 @@ HIC VFWAPI ICGetDisplayFormat(
found = TRUE;
lpbiOut->biBitCount = try_depths[i].depth;
lpbiOut->biCompression = try_depths[i].compression;
- lpbiOut->biSizeImage = dx * dy * lpbiOut->biBitCount / 8;
+ lpbiOut->biSizeImage = dx * get_stride(dy, lpbiOut->biBitCount);
if (ICDecompressQuery(tmphic, lpbiIn, lpbiOut) == ICERR_OK)
+ {
+ if (try_depths[i].depth == 8)
+ ICDecompressGetPalette(tmphic, lpbiIn, lpbiOut);
goto success;
+ }
}
if (!found)
{
lpbiOut->biBitCount = depth;
lpbiOut->biCompression = BI_RGB;
- lpbiOut->biSizeImage = (dx * dy * depth) / 8;
+ lpbiOut->biSizeImage = dx * get_stride(dy, lpbiOut->biBitCount);
if (ICDecompressQuery(tmphic, lpbiIn, lpbiOut) == ICERR_OK)
goto success;
lpbiOut->biBitCount = screen_depth;
lpbiOut->biCompression = BI_RGB;
- lpbiOut->biSizeImage = dx * dy * screen_depth / 8;
+ lpbiOut->biSizeImage = dx * get_stride(dy, lpbiOut->biBitCount);
if (ICDecompressQuery(tmphic, lpbiIn, lpbiOut) == ICERR_OK)
goto success;
}
diff --git a/dlls/msvfw32/tests/msvfw.c b/dlls/msvfw32/tests/msvfw.c
index 252aba2..91628e2 100644
--- a/dlls/msvfw32/tests/msvfw.c
+++ b/dlls/msvfw32/tests/msvfw.c
@@ -25,6 +25,11 @@
#include "wine/test.h"
+static inline int get_stride(int width, int depth)
+{
+ return ((depth * width + 31) >> 3) & ~3;
+}
+
static void test_OpenCase(void)
{
HIC h;
@@ -367,9 +372,30 @@ static struct msg_result expected_msgs[] =
{40, ICM_DECOMPRESS_GET_FORMAT, TRUE, 320, 240, 16, BI_RGB, ICERR_OK, FALSE},
{41, ICM_DECOMPRESS_QUERY, TRUE, 640, 480, 32, BI_RGB, ICERR_OK, FALSE},
+ /* test 11 */
+ {42, ICM_DECOMPRESS_QUERY, FALSE, 0, 0, 0, 0, ICERR_OK, FALSE},
+ {43, ICM_DECOMPRESS_GET_FORMAT, TRUE, 320, 240, 16, BI_RGB, ICERR_OK, FALSE},
+ {44, ICM_DECOMPRESS_QUERY, TRUE, 270, 270, 8, BI_RGB, ICERR_OK, FALSE},
+ {45, ICM_DECOMPRESS_GET_PALETTE, FALSE, 0, 0, 0, 0, ICERR_UNSUPPORTED, FALSE},
+
+ /* test 12 */
+ {46, ICM_DECOMPRESS_QUERY, FALSE, 0, 0, 0, 0, ICERR_OK, FALSE},
+ {47, ICM_DECOMPRESS_GET_FORMAT, TRUE, 320, 240, 16, BI_RGB, ICERR_OK, FALSE},
+ {48, ICM_DECOMPRESS_QUERY, TRUE, 270, 270, 16, BI_RGB, ICERR_OK, FALSE},
+
+ /* test 13 */
+ {49, ICM_DECOMPRESS_QUERY, FALSE, 0, 0, 0, 0, ICERR_OK, FALSE},
+ {50, ICM_DECOMPRESS_GET_FORMAT, TRUE, 320, 240, 16, BI_RGB, ICERR_OK, FALSE},
+ {51, ICM_DECOMPRESS_QUERY, TRUE, 270, 270, 24, BI_RGB, ICERR_OK, FALSE},
+
+ /* test 14 */
+ {52, ICM_DECOMPRESS_QUERY, FALSE, 0, 0, 0, 0, ICERR_OK, FALSE},
+ {53, ICM_DECOMPRESS_GET_FORMAT, TRUE, 320, 240, 16, BI_RGB, ICERR_OK, FALSE},
+ {54, ICM_DECOMPRESS_QUERY, TRUE, 640, 480, 4, BI_RGB, ICERR_OK, FALSE},
+
/* Wine bug - shouldn't be called */
- {42, DRV_DISABLE, FALSE, 0, 0, 0, 0, ICERR_OK, TRUE},
- {42, DRV_FREE, FALSE, 0, 0, 0, 0, ICERR_OK, TRUE},
+ {55, DRV_DISABLE, FALSE, 0, 0, 0, 0, ICERR_OK, TRUE},
+ {55, DRV_FREE, FALSE, 0, 0, 0, 0, ICERR_OK, TRUE},
};
static int msg_index = 0;
@@ -429,8 +455,8 @@ LRESULT WINAPI driver_proc_test(DWORD_PTR dwDriverId, HDRVR hdrvr, UINT msg,
"Expected biBitCount %d, got %d\n", expected->bits, out->biBitCount);
ok(out->biCompression == expected->compression,
"Expected compression %d, got %d\n", expected->compression, out->biCompression);
- ok(out->biSizeImage == (out->biWidth * out->biHeight * out->biBitCount) / 8,
- "Expected biSizeImage %d, got %d\n", (out->biWidth * out->biHeight * out->biBitCount) / 8,
+ ok(out->biSizeImage == get_stride(out->biWidth, out->biBitCount) * out->biHeight,
+ "Expected biSizeImage %d, got %d\n", get_stride(out->biWidth, out->biBitCount) * out->biHeight,
out->biSizeImage);
trace("query -> width: %d, height: %d, bit: %d, compression: %d, size: %d\n",
@@ -496,6 +522,10 @@ void test_ICGetDisplayFormat(void)
{32, 32, 800, 800, 600, 600, 36},
{32, 32, -1, 640, -1, 480, 39},
{32, 32, -90, 640, -60, 480, 42},
+ { 8, 8, 270, 270, 270, 270, 46},
+ {16, 16, 270, 270, 270, 270, 49},
+ {24, 24, 270, 270, 270, 270, 52},
+ { 4, 4, 0, 640, 0, 480, 55},
};
HIC ic, ic2;
@@ -533,9 +563,10 @@ void test_ICGetDisplayFormat(void)
"Expected biWidth %d, got %d\n", tests[i].width_expected, out.biWidth);
ok(out.biHeight == tests[i].height_expected,
"Expected biHeight %d, got %d\n", tests[i].height_expected, out.biHeight);
- real_depth = (out.biBitCount > 32) ? 4 : out.biBitCount / 8;
- ok(out.biSizeImage == out.biWidth * out.biHeight * real_depth,
- "Expected biSizeImage %d, got %d\n", out.biWidth * out.biHeight * real_depth, out.biSizeImage);
+ real_depth = (out.biBitCount > 32) ? 32 : out.biBitCount;
+ ok(out.biSizeImage == get_stride(out.biWidth, real_depth) * out.biHeight,
+ "Expected biSizeImage %d, got %d\n", get_stride(out.biWidth, real_depth) * out.biHeight,
+ out.biSizeImage);
ok(msg_index == tests[i].msg_index,
"Expected msg_index %d, got %d\n", tests[i].msg_index, msg_index);
}
--
2.7.1

View File

@@ -0,0 +1,107 @@
From 855c99952103f3f76d2c38e1471570dee8dbf2c3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sun, 3 Apr 2016 18:22:29 +0200
Subject: iccvid: Fix calculation of stride and size.
---
dlls/iccvid/iccvid.c | 10 +++++++---
dlls/msvfw32/tests/msvfw.c | 40 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+), 3 deletions(-)
diff --git a/dlls/iccvid/iccvid.c b/dlls/iccvid/iccvid.c
index 1ef2db6..0531f31 100644
--- a/dlls/iccvid/iccvid.c
+++ b/dlls/iccvid/iccvid.c
@@ -91,6 +91,10 @@ static inline BOOL heap_free( LPVOID ptr )
return HeapFree( GetProcessHeap(), 0, ptr );
}
+static inline int get_stride(int width, int depth)
+{
+ return ((depth * width + 31) >> 3) & ~3;
+}
/* ------------------------------------------------------------------------ */
static unsigned char *in_buffer, uiclip[1024], *uiclp = NULL;
@@ -459,7 +463,7 @@ static void decode_cinepak(cinepak_info *cvinfo, unsigned char *buf, int size,
break;
}
- frm_stride = out_width * bpp;
+ frm_stride = get_stride(out_width, bpp * 8);
frm_ptr = output;
if(frame.length != size)
@@ -844,9 +848,9 @@ static LRESULT ICCVID_DecompressGetFormat( ICCVID_Info *info, LPBITMAPINFO in, L
if( out )
{
memcpy( out, in, size );
+ out->bmiHeader.biBitCount = 24;
out->bmiHeader.biCompression = BI_RGB;
- out->bmiHeader.biSizeImage = in->bmiHeader.biHeight
- * in->bmiHeader.biWidth *4;
+ out->bmiHeader.biSizeImage = get_stride(in->bmiHeader.biWidth, 24) * in->bmiHeader.biHeight;
return ICERR_OK;
}
return size;
diff --git a/dlls/msvfw32/tests/msvfw.c b/dlls/msvfw32/tests/msvfw.c
index 91628e2..7943184 100644
--- a/dlls/msvfw32/tests/msvfw.c
+++ b/dlls/msvfw32/tests/msvfw.c
@@ -93,6 +93,7 @@ static void test_Locate(void)
{
static BITMAPINFOHEADER bi = {sizeof(BITMAPINFOHEADER),32,8, 1,8, BI_RLE8, 0,100000,100000, 0,0};
static BITMAPINFOHEADER bo = {sizeof(BITMAPINFOHEADER),32,8, 1,8, BI_RGB, 0,100000,100000, 0,0};
+ BITMAPINFOHEADER tmp = {sizeof(BITMAPINFOHEADER)};
HIC h;
DWORD err;
@@ -128,6 +129,45 @@ static void test_Locate(void)
ok(err == ICERR_OK, "Query cvid->RGB32 height<0: %d\n", err);
bo.biHeight = -bo.biHeight;
+ bi.biWidth = 17;
+
+ bi.biBitCount = 8;
+ err = ICDecompressGetFormat(h, &bi, &tmp);
+ ok(err == ICERR_OK, "Query cvid output format: %d\n", err);
+ ok(tmp.biBitCount == 24, "Expected 24 bit, got %d bit\n", tmp.biBitCount);
+ ok(tmp.biSizeImage == get_stride(17, 24) * 8, "Expected size %d, got %d\n",
+ get_stride(17, 24) * 8, tmp.biSizeImage);
+
+ bi.biBitCount = 15;
+ err = ICDecompressGetFormat(h, &bi, &tmp);
+ ok(err == ICERR_OK, "Query cvid output format: %d\n", err);
+ ok(tmp.biBitCount == 24, "Expected 24 bit, got %d bit\n", tmp.biBitCount);
+ ok(tmp.biSizeImage == get_stride(17, 24) * 8, "Expected size %d, got %d\n",
+ get_stride(17, 24) * 8, tmp.biSizeImage);
+
+ bi.biBitCount = 16;
+ err = ICDecompressGetFormat(h, &bi, &tmp);
+ ok(err == ICERR_OK, "Query cvid output format: %d\n", err);
+ ok(tmp.biBitCount == 24, "Expected 24 bit, got %d bit\n", tmp.biBitCount);
+ ok(tmp.biSizeImage == get_stride(17, 24) * 8, "Expected size %d, got %d\n",
+ get_stride(17, 24) * 8, tmp.biSizeImage);
+
+ bi.biBitCount = 24;
+ err = ICDecompressGetFormat(h, &bi, &tmp);
+ ok(err == ICERR_OK, "Query cvid output format: %d\n", err);
+ ok(tmp.biBitCount == 24, "Expected 24 bit, got %d bit\n", tmp.biBitCount);
+ ok(tmp.biSizeImage == get_stride(17, 24) * 8, "Expected size %d, got %d\n",
+ get_stride(17, 24) * 8, tmp.biSizeImage);
+
+ bi.biBitCount = 32;
+ err = ICDecompressGetFormat(h, &bi, &tmp);
+ ok(err == ICERR_OK, "Query cvid output format: %d\n", err);
+ ok(tmp.biBitCount == 24, "Expected 24 bit, got %d bit\n", tmp.biBitCount);
+ ok(tmp.biSizeImage == get_stride(17, 24) * 8, "Expected size %d, got %d\n",
+ get_stride(17, 24) * 8, tmp.biSizeImage);
+
+ bi.biWidth = 32;
+
ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
bo.biBitCount = bi.biBitCount = 8;
--
2.7.1

View File

@@ -0,0 +1,190 @@
From ef25f64580a12fba30413f34c1a9c72e31089e29 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sat, 2 Apr 2016 22:15:37 +0200
Subject: msvidc32: Add support for converting 16 bit depth to 24 bit.
---
dlls/msvfw32/tests/msvfw.c | 5 +++
dlls/msvidc32/msvideo1.c | 91 ++++++++++++++++++++++++++++++++++++++++------
2 files changed, 84 insertions(+), 12 deletions(-)
diff --git a/dlls/msvfw32/tests/msvfw.c b/dlls/msvfw32/tests/msvfw.c
index 125cac5..66956aa 100644
--- a/dlls/msvfw32/tests/msvfw.c
+++ b/dlls/msvfw32/tests/msvfw.c
@@ -202,6 +202,11 @@ static void test_Locate(void)
todo_wine ok(err == ICERR_OK, "Query MSVC->RGB16 height<0: %d\n", err);
bo.biHeight = -bo.biHeight;
+ bo.biBitCount = 24;
+ err = ICDecompressQuery(h, &bi, &bo);
+ ok(err == ICERR_OK, "Query MSVC 16->24: %d\n", err);
+ bo.biBitCount = 16;
+
bi.biCompression = mmioFOURCC('m','s','v','c');
err = ICDecompressQuery(h, &bi, &bo);
ok(err == ICERR_BADFORMAT, "Query msvc->RGB16: %d\n", err);
diff --git a/dlls/msvidc32/msvideo1.c b/dlls/msvidc32/msvideo1.c
index b3faaf6..ab7cc3e 100644
--- a/dlls/msvidc32/msvideo1.c
+++ b/dlls/msvidc32/msvideo1.c
@@ -67,7 +67,7 @@ typedef BYTE uint8_t;
typedef struct Msvideo1Context {
DWORD dwMagic;
- BOOL mode_8bit; /* if it's not 8-bit, it's 16-bit */
+ int depth;
} Msvideo1Context;
static void
@@ -327,8 +327,15 @@ CRAM_DecompressQuery( Msvideo1Context *info, LPBITMAPINFO in, LPBITMAPINFO out )
TRACE("out->bpp = %d\n", out->bmiHeader.biBitCount );
TRACE("out->height = %d\n", out->bmiHeader.biHeight );
TRACE("out->width = %d\n", out->bmiHeader.biWidth );
- if(( in->bmiHeader.biBitCount != out->bmiHeader.biBitCount ) ||
- ( in->bmiHeader.biPlanes != out->bmiHeader.biPlanes ) ||
+
+ if ((in->bmiHeader.biBitCount != out->bmiHeader.biBitCount) &&
+ (in->bmiHeader.biBitCount != 16 || out->bmiHeader.biBitCount != 24))
+ {
+ TRACE("incompatible depth requested\n");
+ return ICERR_BADFORMAT;
+ }
+
+ if(( in->bmiHeader.biPlanes != out->bmiHeader.biPlanes ) ||
( in->bmiHeader.biHeight != out->bmiHeader.biHeight ) ||
( in->bmiHeader.biWidth != out->bmiHeader.biWidth ))
{
@@ -376,21 +383,52 @@ static LRESULT CRAM_DecompressBegin( Msvideo1Context *info, LPBITMAPINFO in, LPB
TRACE("bitmap is %d bpp\n", in->bmiHeader.biBitCount);
if( in->bmiHeader.biBitCount == 8 )
- info->mode_8bit = TRUE;
+ info->depth = 8;
else if( in->bmiHeader.biBitCount == 16 )
- info->mode_8bit = FALSE;
+ info->depth = 16;
else
{
- info->mode_8bit = FALSE;
+ info->depth = 0;
FIXME("Unsupported output format %i\n", in->bmiHeader.biBitCount);
}
return ICERR_OK;
}
+static void convert_depth(char *input, int depth_in, char *output, BITMAPINFOHEADER *out_hdr)
+{
+ int x, y;
+
+ if (depth_in == 16 && out_hdr->biBitCount == 24)
+ {
+ static const unsigned char convert_5to8[] =
+ {
+ 0x00, 0x08, 0x10, 0x19, 0x21, 0x29, 0x31, 0x3a,
+ 0x42, 0x4a, 0x52, 0x5a, 0x63, 0x6b, 0x73, 0x7b,
+ 0x84, 0x8c, 0x94, 0x9c, 0xa5, 0xad, 0xb5, 0xbd,
+ 0xc5, 0xce, 0xd6, 0xde, 0xe6, 0xef, 0xf7, 0xff,
+ };
+
+ WORD *src = (WORD *)input;
+ for (y = 0; y < out_hdr->biHeight; y++)
+ {
+ for (x = 0; x < out_hdr->biWidth; x++)
+ {
+ WORD pixel = *src++;
+ *output++ = convert_5to8[(pixel & 0x7c00u) >> 10];
+ *output++ = convert_5to8[(pixel & 0x03e0u) >> 5];
+ *output++ = convert_5to8[(pixel & 0x001fu)];
+ }
+ }
+ }
+ else
+ FIXME("Conversion from %d to %d bit unimplemented\n", depth_in, out_hdr->biBitCount);
+}
+
static LRESULT CRAM_Decompress( Msvideo1Context *info, ICDECOMPRESS *icd, DWORD size )
{
LONG width, height, stride, sz;
+ void *output;
TRACE("ICM_DECOMPRESS %p %p %d\n", info, icd, size);
@@ -404,15 +442,29 @@ static LRESULT CRAM_Decompress( Msvideo1Context *info, ICDECOMPRESS *icd, DWORD
stride = width; /* in bytes or 16bit words */
sz = icd->lpbiInput->biSizeImage;
- if (info->mode_8bit)
+ output = icd->lpOutput;
+
+ if (icd->lpbiOutput->biBitCount != info->depth)
+ {
+ output = HeapAlloc(GetProcessHeap(), 0, icd->lpbiOutput->biWidth * icd->lpbiOutput->biHeight * info->depth / 8);
+ if (!output) return ICERR_MEMORY;
+ }
+
+ if (info->depth == 8)
{
msvideo1_decode_8bit( width, height, icd->lpInput, sz,
- icd->lpOutput, stride);
+ output, stride );
}
else
{
msvideo1_decode_16bit( width, height, icd->lpInput, sz,
- icd->lpOutput, stride);
+ output, stride );
+ }
+
+ if (icd->lpbiOutput->biBitCount != info->depth)
+ {
+ convert_depth(output, info->depth, icd->lpOutput, icd->lpbiOutput);
+ HeapFree(GetProcessHeap(), 0, output);
}
return ICERR_OK;
@@ -421,6 +473,7 @@ static LRESULT CRAM_Decompress( Msvideo1Context *info, ICDECOMPRESS *icd, DWORD
static LRESULT CRAM_DecompressEx( Msvideo1Context *info, ICDECOMPRESSEX *icd, DWORD size )
{
LONG width, height, stride, sz;
+ void *output;
TRACE("ICM_DECOMPRESSEX %p %p %d\n", info, icd, size);
@@ -434,15 +487,29 @@ static LRESULT CRAM_DecompressEx( Msvideo1Context *info, ICDECOMPRESSEX *icd, DW
stride = width;
sz = icd->lpbiSrc->biSizeImage;
- if (info->mode_8bit)
+ output = icd->lpDst;
+
+ if (icd->lpbiDst->biBitCount != info->depth)
+ {
+ output = HeapAlloc(GetProcessHeap(), 0, icd->lpbiDst->biWidth * icd->lpbiDst->biHeight * info->depth / 8);
+ if (!output) return ICERR_MEMORY;
+ }
+
+ if (info->depth == 8)
{
msvideo1_decode_8bit( width, height, icd->lpSrc, sz,
- icd->lpDst, stride);
+ output, stride );
}
else
{
msvideo1_decode_16bit( width, height, icd->lpSrc, sz,
- icd->lpDst, stride);
+ output, stride );
+ }
+
+ if (icd->lpbiDst->biBitCount != info->depth)
+ {
+ convert_depth(output, info->depth, icd->lpDst, icd->lpbiDst);
+ HeapFree(GetProcessHeap(), 0, output);
}
return ICERR_OK;
--
2.7.1

View File

@@ -0,0 +1,175 @@
From 5d4bb7073d6674407a0a677732805e4d24988f24 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sun, 3 Apr 2016 19:10:42 +0200
Subject: msvidc32: Fix calculation of stride and size.
---
dlls/msvfw32/tests/msvfw.c | 39 +++++++++++++++++++++++++++++++++++++++
dlls/msvidc32/msvideo1.c | 34 +++++++++++++++++++++++++---------
2 files changed, 64 insertions(+), 9 deletions(-)
diff --git a/dlls/msvfw32/tests/msvfw.c b/dlls/msvfw32/tests/msvfw.c
index b546150..03ebaa7 100644
--- a/dlls/msvfw32/tests/msvfw.c
+++ b/dlls/msvfw32/tests/msvfw.c
@@ -252,6 +252,45 @@ static void test_Locate(void)
ok(err == ICERR_OK, "Query MSVC 16->24: %d\n", err);
bo.biBitCount = 16;
+ bi.biWidth = 553;
+
+ bi.biBitCount = 8;
+ err = ICDecompressGetFormat(h, &bi, &tmp);
+ ok(err == ICERR_OK, "Query MSVC output format: %d\n", err);
+ ok(tmp.biBitCount == 8, "Expected 8 bit, got %d bit\n", tmp.biBitCount);
+ ok(tmp.biWidth == 552, "Expected width 552, got %d\n", tmp.biWidth);
+ ok(tmp.biSizeImage == get_stride(552, 8) * 8, "Expected size %d, got %d\n",
+ get_stride(552, 8) * 8, tmp.biSizeImage);
+
+ bi.biBitCount = 15;
+ err = ICDecompressGetFormat(h, &bi, &tmp);
+ ok(err == ICERR_BADFORMAT, "Query MSVC output format: %d\n", err);
+
+ bi.biBitCount = 16;
+ err = ICDecompressGetFormat(h, &bi, &tmp);
+ ok(err == ICERR_OK, "Query MSVC output format: %d\n", err);
+ ok(tmp.biBitCount == 16, "Expected 16 bit, got %d bit\n", tmp.biBitCount);
+ ok(tmp.biWidth == 552, "Expected width 552, got %d\n", tmp.biWidth);
+ ok(tmp.biSizeImage == get_stride(552, 16) * 8, "Expected size %d, got %d\n",
+ get_stride(552, 16) * 8, tmp.biSizeImage);
+
+ bi.biBitCount = 24;
+ err = ICDecompressGetFormat(h, &bi, &tmp);
+ ok(err == ICERR_BADFORMAT, "Query MSVC output format: %d\n", err);
+
+ bi.biBitCount = 32;
+ err = ICDecompressGetFormat(h, &bi, &tmp);
+ ok(err == ICERR_BADFORMAT, "Query MSVC output format: %d\n", err);
+
+ bi.biHeight = 17;
+ bi.biBitCount = 8;
+ err = ICDecompressGetFormat(h, &bi, &tmp);
+ ok(err == ICERR_OK, "Query MSVC output format: %d\n", err);
+ ok(tmp.biHeight == 16, "Expected height 16, got %d\n", tmp.biHeight);
+ bi.biHeight = 8;
+
+ bi.biWidth = 32;
+
bi.biCompression = mmioFOURCC('m','s','v','c');
err = ICDecompressQuery(h, &bi, &bo);
ok(err == ICERR_BADFORMAT, "Query msvc->RGB16: %d\n", err);
diff --git a/dlls/msvidc32/msvideo1.c b/dlls/msvidc32/msvideo1.c
index ab7cc3e..b999b52 100644
--- a/dlls/msvidc32/msvideo1.c
+++ b/dlls/msvidc32/msvideo1.c
@@ -70,6 +70,11 @@ typedef struct Msvideo1Context {
int depth;
} Msvideo1Context;
+static inline int get_stride(int width, int depth)
+{
+ return ((depth * width + 31) >> 3) & ~3;
+}
+
static void
msvideo1_decode_8bit( int width, int height, const unsigned char *buf, int buf_size,
unsigned char *pixels, int stride)
@@ -362,12 +367,17 @@ CRAM_DecompressGetFormat( Msvideo1Context *info, LPBITMAPINFO in, LPBITMAPINFO o
if (in->bmiHeader.biBitCount <= 8)
size += in->bmiHeader.biClrUsed * sizeof(RGBQUAD);
+ if (in->bmiHeader.biBitCount != 8 && in->bmiHeader.biBitCount != 16)
+ return ICERR_BADFORMAT;
+
if( out )
{
memcpy( out, in, size );
+ out->bmiHeader.biWidth = in->bmiHeader.biWidth & ~1;
+ out->bmiHeader.biHeight = in->bmiHeader.biHeight & ~1;
out->bmiHeader.biCompression = BI_RGB;
- out->bmiHeader.biSizeImage = in->bmiHeader.biHeight
- * in->bmiHeader.biWidth *4;
+ out->bmiHeader.biSizeImage = in->bmiHeader.biHeight *
+ get_stride(out->bmiHeader.biWidth, out->bmiHeader.biBitCount);
return ICERR_OK;
}
@@ -398,6 +408,8 @@ static LRESULT CRAM_DecompressBegin( Msvideo1Context *info, LPBITMAPINFO in, LPB
static void convert_depth(char *input, int depth_in, char *output, BITMAPINFOHEADER *out_hdr)
{
int x, y;
+ int stride_in = get_stride(out_hdr->biWidth, depth_in);
+ int stride_out = get_stride(out_hdr->biWidth, out_hdr->biBitCount);
if (depth_in == 16 && out_hdr->biBitCount == 24)
{
@@ -409,15 +421,17 @@ static void convert_depth(char *input, int depth_in, char *output, BITMAPINFOHEA
0xc5, 0xce, 0xd6, 0xde, 0xe6, 0xef, 0xf7, 0xff,
};
- WORD *src = (WORD *)input;
for (y = 0; y < out_hdr->biHeight; y++)
{
+ WORD *src_row = (WORD *)(input + y * stride_in);
+ char *out_row = output + y * stride_out;
+
for (x = 0; x < out_hdr->biWidth; x++)
{
- WORD pixel = *src++;
- *output++ = convert_5to8[(pixel & 0x7c00u) >> 10];
- *output++ = convert_5to8[(pixel & 0x03e0u) >> 5];
- *output++ = convert_5to8[(pixel & 0x001fu)];
+ WORD pixel = *src_row++;
+ *out_row++ = convert_5to8[(pixel & 0x7c00u) >> 10];
+ *out_row++ = convert_5to8[(pixel & 0x03e0u) >> 5];
+ *out_row++ = convert_5to8[(pixel & 0x001fu)];
}
}
}
@@ -439,7 +453,6 @@ static LRESULT CRAM_Decompress( Msvideo1Context *info, ICDECOMPRESS *icd, DWORD
width = icd->lpbiInput->biWidth;
height = icd->lpbiInput->biHeight;
- stride = width; /* in bytes or 16bit words */
sz = icd->lpbiInput->biSizeImage;
output = icd->lpOutput;
@@ -452,11 +465,13 @@ static LRESULT CRAM_Decompress( Msvideo1Context *info, ICDECOMPRESS *icd, DWORD
if (info->depth == 8)
{
+ stride = get_stride(width, 8);
msvideo1_decode_8bit( width, height, icd->lpInput, sz,
output, stride );
}
else
{
+ stride = get_stride(width, 16) / 2;
msvideo1_decode_16bit( width, height, icd->lpInput, sz,
output, stride );
}
@@ -484,7 +499,6 @@ static LRESULT CRAM_DecompressEx( Msvideo1Context *info, ICDECOMPRESSEX *icd, DW
width = icd->lpbiSrc->biWidth;
height = icd->lpbiSrc->biHeight;
- stride = width;
sz = icd->lpbiSrc->biSizeImage;
output = icd->lpDst;
@@ -497,11 +511,13 @@ static LRESULT CRAM_DecompressEx( Msvideo1Context *info, ICDECOMPRESSEX *icd, DW
if (info->depth == 8)
{
+ stride = get_stride(width, 8);
msvideo1_decode_8bit( width, height, icd->lpSrc, sz,
output, stride );
}
else
{
+ stride = get_stride(width, 16) / 2;
msvideo1_decode_16bit( width, height, icd->lpSrc, sz,
output, stride );
}
--
2.7.1

View File

@@ -1,2 +1,3 @@
Fixes: [23175] Fix implementation of ICGetDisplayFormat
Fixes: [25180] Fix rendering of Clonk Endeavour's intro video
Fixes: [14695] Implement support for converting 16 bit depth to 24 bit in msvidc32