iccvid: Implement inverted frame decompressing.

Signed-off-by: Bruno Jesus <00cpxxx@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
oldstable
Bruno Jesus 2015-11-02 03:02:46 +08:00 committed by Alexandre Julliard
parent 9178d037d7
commit e75f2282ba
2 changed files with 105 additions and 84 deletions

View File

@ -141,6 +141,15 @@ int uvr, uvg, uvb;
}
}
static inline long get_addr(BOOL inverted, unsigned long x, unsigned long y,
int frm_stride, int bpp, unsigned int out_height)
{
/* Returns the starting position of a line from top-down or bottom-up */
if (inverted)
return y * frm_stride + x * bpp;
else
return (out_height - 1 - y) * frm_stride + x * bpp;
}
#define MAKECOLOUR32(r,g,b) (((r) << 16) | ((g) << 8) | (b))
/*#define MAKECOLOUR24(r,g,b) (((r) << 16) | ((g) << 8) | (b))*/
@ -148,16 +157,18 @@ int uvr, uvg, uvb;
#define MAKECOLOUR15(r,g,b) (((r) >> 3) << 10)| (((g) >> 3) << 5)| (((b) >> 3) << 0)
/* ------------------------------------------------------------------------ */
static void cvid_v1_32(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb)
static void cvid_v1_32(unsigned char *frm, unsigned char *limit, int stride, BOOL inverted,
cvid_codebook *cb)
{
unsigned long *vptr = (unsigned long *)frm;
#ifndef ORIGINAL
int row_inc = -stride/4;
#else
int row_inc = stride/4;
#endif
int row_inc;
int x, y;
if (!inverted)
row_inc = -stride/4;
else
row_inc = stride/4;
/* fill 4x4 block of pixels with colour values from codebook */
for (y = 0; y < 4; y++)
{
@ -169,18 +180,19 @@ int x, y;
/* ------------------------------------------------------------------------ */
static void cvid_v4_32(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb0,
cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
static void cvid_v4_32(unsigned char *frm, unsigned char *limit, int stride, BOOL inverted,
cvid_codebook *cb0, cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
{
unsigned long *vptr = (unsigned long *)frm;
#ifndef ORIGINAL
int row_inc = -stride/4;
#else
int row_inc = stride/4;
#endif
int row_inc;
int x, y;
cvid_codebook * cb[] = {cb0,cb1,cb2,cb3};
if (!inverted)
row_inc = -stride/4;
else
row_inc = stride/4;
/* fill 4x4 block of pixels with colour values from codebooks */
for (y = 0; y < 4; y++)
{
@ -192,15 +204,17 @@ cvid_codebook * cb[] = {cb0,cb1,cb2,cb3};
/* ------------------------------------------------------------------------ */
static void cvid_v1_24(unsigned char *vptr, unsigned char *limit, int stride, cvid_codebook *cb)
static void cvid_v1_24(unsigned char *vptr, unsigned char *limit, int stride, BOOL inverted,
cvid_codebook *cb)
{
#ifndef ORIGINAL
int row_inc = -stride;
#else
int row_inc = stride;
#endif
int row_inc;
int x, y;
if (!inverted)
row_inc = -stride;
else
row_inc = stride;
/* fill 4x4 block of pixels with colour values from codebook */
for (y = 0; y < 4; y++)
{
@ -216,17 +230,18 @@ int x, y;
/* ------------------------------------------------------------------------ */
static void cvid_v4_24(unsigned char *vptr, unsigned char *limit, int stride, cvid_codebook *cb0,
cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
static void cvid_v4_24(unsigned char *vptr, unsigned char *limit, int stride, BOOL inverted,
cvid_codebook *cb0, cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
{
#ifndef ORIGINAL
int row_inc = -stride;
#else
int row_inc = stride;
#endif
int row_inc;
cvid_codebook * cb[] = {cb0,cb1,cb2,cb3};
int x, y;
if (!inverted)
row_inc = -stride;
else
row_inc = stride;
/* fill 4x4 block of pixels with colour values from codebooks */
for (y = 0; y < 4; y++)
{
@ -242,16 +257,18 @@ int x, y;
/* ------------------------------------------------------------------------ */
static void cvid_v1_16(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb)
static void cvid_v1_16(unsigned char *frm, unsigned char *limit, int stride, BOOL inverted,
cvid_codebook *cb)
{
unsigned short *vptr = (unsigned short *)frm;
#ifndef ORIGINAL
int row_inc = -stride/2;
#else
int row_inc = stride/2;
#endif
int row_inc;
int x, y;
if (!inverted)
row_inc = -stride/2;
else
row_inc = stride/2;
/* fill 4x4 block of pixels with colour values from codebook */
for (y = 0; y < 4; y++)
{
@ -263,18 +280,19 @@ int x, y;
/* ------------------------------------------------------------------------ */
static void cvid_v4_16(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb0,
cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
static void cvid_v4_16(unsigned char *frm, unsigned char *limit, int stride, BOOL inverted,
cvid_codebook *cb0, cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
{
unsigned short *vptr = (unsigned short *)frm;
#ifndef ORIGINAL
int row_inc = -stride/2;
#else
int row_inc = stride/2;
#endif
int row_inc;
cvid_codebook * cb[] = {cb0,cb1,cb2,cb3};
int x, y;
if (!inverted)
row_inc = -stride/2;
else
row_inc = stride/2;
/* fill 4x4 block of pixels with colour values from codebooks */
for (y = 0; y < 4; y++)
{
@ -285,16 +303,18 @@ int x, y;
}
/* ------------------------------------------------------------------------ */
static void cvid_v1_15(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb)
static void cvid_v1_15(unsigned char *frm, unsigned char *limit, int stride, BOOL inverted,
cvid_codebook *cb)
{
unsigned short *vptr = (unsigned short *)frm;
#ifndef ORIGINAL
int row_inc = -stride/2;
#else
int row_inc = stride/2;
#endif
int row_inc;
int x, y;
if (!inverted)
row_inc = -stride/2;
else
row_inc = stride/2;
/* fill 4x4 block of pixels with colour values from codebook */
for (y = 0; y < 4; y++)
{
@ -306,18 +326,19 @@ int x, y;
/* ------------------------------------------------------------------------ */
static void cvid_v4_15(unsigned char *frm, unsigned char *limit, int stride, cvid_codebook *cb0,
cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
static void cvid_v4_15(unsigned char *frm, unsigned char *limit, int stride, BOOL inverted,
cvid_codebook *cb0, cvid_codebook *cb1, cvid_codebook *cb2, cvid_codebook *cb3)
{
unsigned short *vptr = (unsigned short *)frm;
#ifndef ORIGINAL
int row_inc = -stride/2;
#else
int row_inc = stride/2;
#endif
int row_inc;
cvid_codebook * cb[] = {cb0,cb1,cb2,cb3};
int x, y;
if (!inverted)
row_inc = -stride/2;
else
row_inc = stride/2;
/* fill 4x4 block of pixels with colour values from codebooks */
for (y = 0; y < 4; y++)
{
@ -365,8 +386,9 @@ static void free_cvinfo( cinepak_info *cvinfo )
}
typedef void (*fn_cvid_v1)(unsigned char *frm, unsigned char *limit,
int stride, cvid_codebook *cb);
typedef void (*fn_cvid_v4)(unsigned char *frm, unsigned char *limit, int stride,
int stride, BOOL inverted, cvid_codebook *cb);
typedef void (*fn_cvid_v4)(unsigned char *frm, unsigned char *limit,
int stride, BOOL inverted,
cvid_codebook *cb0, cvid_codebook *cb1,
cvid_codebook *cb2, cvid_codebook *cb3);
@ -390,7 +412,7 @@ static void decode_cinepak(cinepak_info *cvinfo, unsigned char *buf, int size,
x0, y0, x1, y1, ci, flag, mask;
long top_size, chunk_size;
unsigned char *frm_ptr;
unsigned int i, cur_strip;
unsigned int i, cur_strip, addr;
int d0, d1, d2, d3, frm_stride, bpp = 3;
fn_cvid_v1 cvid_v1 = cvid_v1_24;
fn_cvid_v4 cvid_v4 = cvid_v4_24;
@ -402,10 +424,13 @@ static void decode_cinepak(cinepak_info *cvinfo, unsigned char *buf, int size,
unsigned short height;
unsigned short strips;
} frame;
BOOL inverted;
y = 0;
y_bottom = 0;
in_buffer = buf;
inverted = (int) out_height < 0;
if (inverted) out_height = -out_height;
frame.flags = get_byte();
frame.length = get_byte() << 16;
@ -601,19 +626,15 @@ static void decode_cinepak(cinepak_info *cvinfo, unsigned char *buf, int size,
d2 = get_byte();
d3 = get_byte();
chunk_size -= 4;
#ifdef ORIGINAL
cvid_v4(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3);
#else
cvid_v4(frm_ptr + ((out_height - 1 - y) * frm_stride + x * bpp), output, frm_stride, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3);
#endif
addr = get_addr(inverted, x, y, frm_stride, bpp, out_height);
cvid_v4(frm_ptr + addr, output, frm_stride, inverted, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3);
}
else /* 1 byte per block */
{
#ifdef ORIGINAL
cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte());
#else
cvid_v1(frm_ptr + ((out_height - 1 - y) * frm_stride + x * bpp), output, frm_stride, v1_codebook + get_byte());
#endif
addr = get_addr(inverted, x, y, frm_stride, bpp, out_height);
cvid_v1(frm_ptr + addr, output, frm_stride, inverted, v1_codebook + get_byte());
chunk_size--;
}
@ -657,20 +678,16 @@ static void decode_cinepak(cinepak_info *cvinfo, unsigned char *buf, int size,
d2 = get_byte();
d3 = get_byte();
chunk_size -= 4;
#ifdef ORIGINAL
cvid_v4(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3);
#else
cvid_v4(frm_ptr + ((out_height - 1 - y) * frm_stride + x * bpp), output, frm_stride, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3);
#endif
addr = get_addr(inverted, x, y, frm_stride, bpp, out_height);
cvid_v4(frm_ptr + addr, output, frm_stride, inverted, v4_codebook+d0, v4_codebook+d1, v4_codebook+d2, v4_codebook+d3);
}
else /* V1 */
{
chunk_size--;
#ifdef ORIGINAL
cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte());
#else
cvid_v1(frm_ptr + ((out_height - 1 - y) * frm_stride + x * bpp), output, frm_stride, v1_codebook + get_byte());
#endif
addr = get_addr(inverted, x, y, frm_stride, bpp, out_height);
cvid_v1(frm_ptr + addr, output, frm_stride, inverted, v1_codebook + get_byte());
}
} /* else SKIP */
@ -690,11 +707,9 @@ static void decode_cinepak(cinepak_info *cvinfo, unsigned char *buf, int size,
case 0x3200: /* each byte is a V1 codebook */
while((chunk_size > 0) && (y < y_bottom))
{
#ifdef ORIGINAL
cvid_v1(frm_ptr + (y * frm_stride + x * bpp), frm_end, frm_stride, v1_codebook + get_byte());
#else
cvid_v1(frm_ptr + ((out_height - 1 - y) * frm_stride + x * bpp), output, frm_stride, v1_codebook + get_byte());
#endif
addr = get_addr(inverted, x, y, frm_stride, bpp, out_height);
cvid_v1(frm_ptr + addr, output, frm_stride, inverted, v1_codebook + get_byte());
chunk_size--;
x += 4;
if(x >= out_width)
@ -782,7 +797,11 @@ static LRESULT ICCVID_DecompressQuery( ICCVID_Info *info, LPBITMAPINFO in, LPBIT
if( in->bmiHeader.biPlanes != out->bmiHeader.biPlanes )
return ICERR_BADFORMAT;
if( in->bmiHeader.biHeight != out->bmiHeader.biHeight )
return ICERR_BADFORMAT;
{
if( in->bmiHeader.biHeight != -out->bmiHeader.biHeight )
return ICERR_BADFORMAT;
TRACE("Detected inverted height for video output\n");
}
if( in->bmiHeader.biWidth != out->bmiHeader.biWidth )
return ICERR_BADFORMAT;
@ -887,6 +906,7 @@ static LRESULT ICCVID_Decompress( ICCVID_Info *info, ICDECOMPRESS *icd, DWORD si
width = icd->lpbiInput->biWidth;
height = icd->lpbiInput->biHeight;
if (-icd->lpbiOutput->biHeight == height) height = -height;
decode_cinepak(info->cvinfo, icd->lpInput, icd->lpbiInput->biSizeImage,
icd->lpOutput, width, height, info->bits_per_pixel);
@ -912,6 +932,7 @@ static LRESULT ICCVID_DecompressEx( ICCVID_Info *info, ICDECOMPRESSEX *icd, DWOR
width = icd->lpbiSrc->biWidth;
height = icd->lpbiSrc->biHeight;
if (-icd->lpbiDst->biHeight == height) height = -height;
decode_cinepak(info->cvinfo, icd->lpSrc, icd->lpbiSrc->biSizeImage,
icd->lpDst, width, height, info->bits_per_pixel);

View File

@ -120,7 +120,7 @@ static void test_Locate(void)
bo.biHeight = -bo.biHeight;
err = ICDecompressQuery(h, &bi, &bo);
todo_wine ok(err == ICERR_OK, "Query cvid->RGB32 height<0: %d\n", err);
ok(err == ICERR_OK, "Query cvid->RGB32 height<0: %d\n", err);
bo.biHeight = -bo.biHeight;
ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
@ -141,7 +141,7 @@ static void test_Locate(void)
if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
bo.biHeight = - bo.biHeight;
h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
todo_wine ok(h != 0, "cvid->RGB16 height<0 failed\n");
ok(h != 0, "cvid->RGB16 height<0 failed\n");
if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
bo.biHeight = - bo.biHeight;
@ -151,7 +151,7 @@ static void test_Locate(void)
if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
bo.biHeight = - bo.biHeight;
h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
todo_wine ok(h != 0, "cvid->RGB32 height<0 failed\n");
ok(h != 0, "cvid->RGB32 height<0 failed\n");
if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
bo.biHeight = - bo.biHeight;