[ICCVID] Sync with Wine Staging 3.3. CORE-14434
[reactos.git] / dll / win32 / iccvid / iccvid.c
index bdca812..3977d95 100644 (file)
  *       Tim Ferguson: http://www.csse.monash.edu.au/~timf/
  * ------------------------------------------------------------------------ */
 
-#define WIN32_NO_STATUS
-#define _INC_WINDOWS
-#define COM_NO_WINDOWS_H
-
 #include <stdarg.h>
-#include <windef.h>
-#include <winbase.h>
-#include <wingdi.h>
-//#include "winuser.h"
-//#include "commdlg.h"
-#include <vfw.h>
-//#include "mmsystem.h"
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "commdlg.h"
+#include "vfw.h"
+#include "mmsystem.h"
 #include "iccvid_private.h"
 
-#include <wine/debug.h>
+#include "wine/debug.h"
+#include "wine/heap.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(iccvid);
 
@@ -62,8 +59,6 @@ static HINSTANCE ICCVID_hModule;
 
 #define ICCVID_MAGIC mmioFOURCC('c', 'v', 'i', 'd')
 #define compare_fourcc(fcc1, fcc2) (((fcc1)^(fcc2))&~0x20202020)
-
-#define DBUG    0
 #define MAX_STRIPS 32
 
 /* ------------------------------------------------------------------------ */
@@ -87,16 +82,6 @@ typedef struct _ICCVID_Info
     cinepak_info *cvinfo;
 } ICCVID_Info;
 
-static inline LPVOID heap_alloc( size_t size )
-{
-    return HeapAlloc( GetProcessHeap(), 0, size );
-}
-
-static inline BOOL heap_free( LPVOID ptr )
-{
-    return HeapFree( GetProcessHeap(), 0, ptr );
-}
-
 
 /* ------------------------------------------------------------------------ */
 static unsigned char *in_buffer, uiclip[1024], *uiclp = NULL;
@@ -147,6 +132,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))*/
@@ -154,16 +148,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++)
     {
@@ -173,20 +169,25 @@ int x, y;
     }
 }
 
+static inline int get_stride(int width, int depth)
+{
+    return ((depth * width + 31) >> 3) & ~3;
+}
 
 /* ------------------------------------------------------------------------ */
-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++)
     {
@@ -198,15 +199,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++)
     {
@@ -222,17 +225,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++)
     {
@@ -248,16 +252,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++)
     {
@@ -269,18 +275,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++)
     {
@@ -291,16 +298,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++)
     {
@@ -312,18 +321,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++)
     {
@@ -371,8 +381,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);
 
@@ -382,33 +393,42 @@ typedef void (*fn_cvid_v4)(unsigned char *frm, unsigned char *limit, int stride,
  * context - the context created by decode_cinepak_init().
  * buf - the input buffer to be decoded
  * size - the size of the input buffer
- * frame - the output frame buffer (24 or 32 bit per pixel)
- * width - the width of the output frame
- * height - the height of the output frame
+ * output - the output frame buffer (24 or 32 bit per pixel)
+ * out_width - the width of the output frame
+ * out_height - the height of the output frame
  * bit_per_pixel - the number of bits per pixel allocated to the output
  *   frame (only 24 or 32 bpp are supported)
+ * inverted - if true the output frame is written top-down
  */
 static void decode_cinepak(cinepak_info *cvinfo, unsigned char *buf, int size,
-           unsigned char *frame, unsigned int width, unsigned int height, int bit_per_pixel)
+           unsigned char *output, unsigned int out_width, unsigned int out_height, int bit_per_pixel, BOOL inverted)
 {
     cvid_codebook *v4_codebook, *v1_codebook, *codebook = NULL;
-    unsigned long x, y, y_bottom, frame_flags, strips, cv_width, cv_height,
-                  cnum, strip_id, chunk_id, x0, y0, x1, y1, ci, flag, mask;
-    long len, top_size, chunk_size;
+    unsigned long x, y, y_bottom, cnum, strip_id, chunk_id,
+                  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;
+    struct frame_header
+    {
+      unsigned char flags;
+      unsigned long length;
+      unsigned short width;
+      unsigned short height;
+      unsigned short strips;
+    } frame;
 
     y = 0;
     y_bottom = 0;
     in_buffer = buf;
 
-    frame_flags = get_byte();
-    len = get_byte() << 16;
-    len |= get_byte() << 8;
-    len |= get_byte();
+    frame.flags = get_byte();
+    frame.length = get_byte() << 16;
+    frame.length |= get_byte() << 8;
+    frame.length |= get_byte();
 
     switch(bit_per_pixel)
         {
@@ -434,32 +454,32 @@ static void decode_cinepak(cinepak_info *cvinfo, unsigned char *buf, int size,
             break;
         }
 
-    frm_stride = width * bpp;
-    frm_ptr = frame;
+    frm_stride = get_stride(out_width, bpp * 8);
+    frm_ptr = output;
 
-    if(len != size)
+    if(frame.length != size)
         {
-        if(len & 0x01) len++; /* AVIs tend to have a size mismatch */
-        if(len != size)
+        if(frame.length & 0x01) frame.length++; /* AVIs tend to have a size mismatch */
+        if(frame.length != size)
             {
-            ERR("CVID: corruption %d (QT/AVI) != %ld (CV)\n", size, len);
+            ERR("CVID: corruption %d (QT/AVI) != %ld (CV)\n", size, frame.length);
             /* return; */
             }
         }
 
-    cv_width = get_word();
-    cv_height = get_word();
-    strips = get_word();
+    frame.width = get_word();
+    frame.height = get_word();
+    frame.strips = get_word();
 
-    if(strips > cvinfo->strip_num)
+    if(frame.strips > cvinfo->strip_num)
         {
-        if(strips >= MAX_STRIPS)
+        if(frame.strips >= MAX_STRIPS)
             {
             ERR("CVID: strip overflow (more than %d)\n", MAX_STRIPS);
             return;
             }
 
-        for(i = cvinfo->strip_num; i < strips; i++)
+        for(i = cvinfo->strip_num; i < frame.strips; i++)
             {
             if((cvinfo->v4_codebook[i] = heap_alloc(sizeof(cvid_codebook) * 260)) == NULL)
                 {
@@ -474,16 +494,17 @@ static void decode_cinepak(cinepak_info *cvinfo, unsigned char *buf, int size,
                 }
             }
         }
-    cvinfo->strip_num = strips;
+    cvinfo->strip_num = frame.strips;
 
-    TRACE("CVID: <%ld,%ld> strips %ld\n", cv_width, cv_height, strips);
+    TRACE("CVID: %ux%u, strips %u, length %lu\n",
+          frame.width, frame.height, frame.strips, frame.length);
 
-    for(cur_strip = 0; cur_strip < strips; cur_strip++)
+    for(cur_strip = 0; cur_strip < frame.strips; cur_strip++)
         {
         v4_codebook = cvinfo->v4_codebook[cur_strip];
         v1_codebook = cvinfo->v1_codebook[cur_strip];
 
-        if((cur_strip > 0) && (!(frame_flags & 0x01)))
+        if((cur_strip > 0) && (!(frame.flags & 0x01)))
             {
             memcpy(cvinfo->v4_codebook[cur_strip], cvinfo->v4_codebook[cur_strip-1], 260 * sizeof(cvid_codebook));
             memcpy(cvinfo->v1_codebook[cur_strip], cvinfo->v1_codebook[cur_strip-1], 260 * sizeof(cvid_codebook));
@@ -499,8 +520,8 @@ static void decode_cinepak(cinepak_info *cvinfo, unsigned char *buf, int size,
         y_bottom += y1;
         top_size -= 12;
         x = 0;
-        if(x1 != width)
-            WARN("CVID: Warning x1 (%ld) != width (%d)\n", x1, width);
+        if(x1 != out_width)
+            WARN("CVID: Warning x1 (%ld) != width (%d)\n", x1, out_width);
 
         TRACE("   %d) %04lx %04ld <%ld,%ld> <%ld,%ld> yt %ld\n",
               cur_strip, strip_id, top_size, x0, y0, x1, y1, y_bottom);
@@ -598,24 +619,20 @@ 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 + ((height - 1 - y) * frm_stride + x * bpp), frame, 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 + ((height - 1 - y) * frm_stride + x * bpp), frame, 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 >= width)
+                            if(x >= out_width)
                                 {
                                 x = 0;
                                 y += 4;
@@ -654,26 +671,22 @@ 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 + ((height - 1 - y) * frm_stride + x * bpp), frame, 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 + ((height - 1 - y) * frm_stride + x * bpp), frame, 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 */
 
                             mask >>= 1;
                             x += 4;
-                            if(x >= width)
+                            if(x >= out_width)
                                 {
                                 x = 0;
                                 y += 4;
@@ -687,14 +700,12 @@ 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 + ((height - 1 - y) * frm_stride + x * bpp), frame, 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 >= width)
+                        if(x >= out_width)
                             {
                             x = 0;
                             y += 4;
@@ -711,10 +722,10 @@ static void decode_cinepak(cinepak_info *cvinfo, unsigned char *buf, int size,
             }
         }
 
-    if(len != size)
+    if(frame.length != size)
         {
-        if(len & 0x01) len++; /* AVIs tend to have a size mismatch */
-        if(len != size)
+        if(frame.length & 0x01) frame.length++; /* AVIs tend to have a size mismatch */
+        if(frame.length != size)
             {
             long xlen;
             skip_byte();
@@ -722,7 +733,7 @@ static void decode_cinepak(cinepak_info *cvinfo, unsigned char *buf, int size,
             xlen |= get_byte() << 8;
             xlen |= get_byte(); /* Read Len */
             WARN("CVID: END INFO chunk size %d cvid size1 %ld cvid size2 %ld\n",
-                  size, len, xlen);
+                  size, frame.length, xlen);
             }
         }
 }
@@ -779,7 +790,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;
 
@@ -824,9 +839,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;
@@ -871,6 +886,7 @@ static LRESULT ICCVID_DecompressBegin( ICCVID_Info *info, LPBITMAPINFO in, LPBIT
 static LRESULT ICCVID_Decompress( ICCVID_Info *info, ICDECOMPRESS *icd, DWORD size )
 {
     LONG width, height;
+    BOOL inverted;
 
     TRACE("ICM_DECOMPRESS %p %p %d\n", info, icd, size);
 
@@ -884,9 +900,10 @@ static LRESULT ICCVID_Decompress( ICCVID_Info *info, ICDECOMPRESS *icd, DWORD si
 
     width  = icd->lpbiInput->biWidth;
     height = icd->lpbiInput->biHeight;
+    inverted = -icd->lpbiOutput->biHeight == height;
 
     decode_cinepak(info->cvinfo, icd->lpInput, icd->lpbiInput->biSizeImage,
-                   icd->lpOutput, width, height, info->bits_per_pixel);
+                   icd->lpOutput, width, height, info->bits_per_pixel, inverted);
 
     return ICERR_OK;
 }
@@ -894,6 +911,7 @@ static LRESULT ICCVID_Decompress( ICCVID_Info *info, ICDECOMPRESS *icd, DWORD si
 static LRESULT ICCVID_DecompressEx( ICCVID_Info *info, ICDECOMPRESSEX *icd, DWORD size )
 {
     LONG width, height;
+    BOOL inverted;
 
     TRACE("ICM_DECOMPRESSEX %p %p %d\n", info, icd, size);
 
@@ -909,9 +927,10 @@ static LRESULT ICCVID_DecompressEx( ICCVID_Info *info, ICDECOMPRESSEX *icd, DWOR
 
     width  = icd->lpbiSrc->biWidth;
     height = icd->lpbiSrc->biHeight;
+    inverted = -icd->lpbiDst->biHeight == height;
 
     decode_cinepak(info->cvinfo, icd->lpSrc, icd->lpbiSrc->biSizeImage,
-                   icd->lpDst, width, height, info->bits_per_pixel);
+                   icd->lpDst, width, height, info->bits_per_pixel, inverted);
 
     return ICERR_OK;
 }
@@ -1039,9 +1058,6 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved)
         DisableThreadLibraryCalls(hModule);
         ICCVID_hModule = hModule;
         break;
-
-    case DLL_PROCESS_DETACH:
-        break;
     }
     return TRUE;
 }