[MSRLE32] Sync with Wine Staging 4.18. CORE-16441
[reactos.git] / dll / win32 / msrle32 / msrle32.c
index 146f7e7..5b17b25 100644 (file)
 
 #include "msrle_private.h"
 
-//#include "winnls.h"
-//#include "winuser.h"
+#include "winnls.h"
+#include "winuser.h"
 
-#include <wine/debug.h>
+#include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(msrle32);
 
@@ -36,13 +36,10 @@ static HINSTANCE MSRLE32_hModule = 0;
 
 #define compare_fourcc(fcc1, fcc2) (((fcc1)^(fcc2))&~0x20202020)
 
-#define ABS(a)                ((a) < 0 ? -(a) : (a))
-#define SQR(a)                ((a) * (a))
-
 static inline WORD ColorCmp(WORD clr1, WORD clr2)
 {
   UINT a = clr1 - clr2;
-  return SQR(a);
+  return a * a;
 }
 static inline WORD Intensity(RGBQUAD clr)
 {
@@ -1186,8 +1183,8 @@ static LRESULT GetInfo(const CodecInfo *pi, ICINFO *icinfo, DWORD dwSize)
   icinfo->dwVersion    = ICVERSION;
   icinfo->dwVersionICM = ICVERSION;
 
-  LoadStringW(MSRLE32_hModule, IDS_NAME, icinfo->szName, sizeof(icinfo->szName)/sizeof(WCHAR));
-  LoadStringW(MSRLE32_hModule, IDS_DESCRIPTION, icinfo->szDescription, sizeof(icinfo->szDescription)/sizeof(WCHAR));
+  LoadStringW(MSRLE32_hModule, IDS_NAME, icinfo->szName, ARRAY_SIZE(icinfo->szName));
+  LoadStringW(MSRLE32_hModule, IDS_DESCRIPTION, icinfo->szDescription, ARRAY_SIZE(icinfo->szDescription));
 
   return sizeof(ICINFO);
 }
@@ -1209,8 +1206,8 @@ static LRESULT About(CodecInfo *pi, HWND hWnd)
   /* pre-condition */
   assert(MSRLE32_hModule != 0);
 
-  LoadStringW(MSRLE32_hModule, IDS_NAME, szTitle, sizeof(szTitle)/sizeof(szTitle[0]));
-  LoadStringW(MSRLE32_hModule, IDS_ABOUT, szAbout, sizeof(szAbout)/sizeof(szAbout[0]));
+  LoadStringW(MSRLE32_hModule, IDS_NAME, szTitle, ARRAY_SIZE(szTitle));
+  LoadStringW(MSRLE32_hModule, IDS_ABOUT, szAbout, ARRAY_SIZE(szAbout));
 
   MessageBoxW(hWnd, szAbout, szTitle, MB_OK|MB_ICONINFORMATION);
 
@@ -1547,6 +1544,11 @@ static LRESULT CompressEnd(CodecInfo *pi)
     pi->pCurFrame  = NULL;
     pi->nPrevFrame = -1;
     pi->bCompress  = FALSE;
+
+    if (pi->palette_map != NULL) {
+        LocalFree(pi->palette_map);
+        pi->palette_map = NULL;
+    }
   }
 
   return ICERR_OK;
@@ -1570,8 +1572,16 @@ static LRESULT DecompressGetFormat(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn,
 
   size = lpbiIn->biSize;
 
-  if (lpbiIn->biBitCount <= 8)
-    size += lpbiIn->biClrUsed * sizeof(RGBQUAD);
+  if (lpbiIn->biBitCount <= 8) {
+    int colors;
+
+    if (lpbiIn->biClrUsed == 0)
+      colors = 1 << lpbiIn->biBitCount;
+    else
+      colors = lpbiIn->biClrUsed;
+
+    size += colors * sizeof(RGBQUAD);
+  }
 
   if (lpbiOut != NULL) {
     memcpy(lpbiOut, lpbiIn, size);
@@ -1599,7 +1609,7 @@ static LRESULT DecompressQuery(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn,
 
   /* check input format if given */
   if (lpbiIn != NULL) {
-    if (!isSupportedMRLE(lpbiIn))
+    if (!isSupportedMRLE(lpbiIn) && !isSupportedDIB(lpbiIn))
       return ICERR_BADFORMAT;
   }
 
@@ -1610,11 +1620,11 @@ static LRESULT DecompressQuery(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn,
 
     if (lpbiIn != NULL) {
       if (lpbiIn->biWidth  != lpbiOut->biWidth)
-       hr = ICERR_UNSUPPORTED;
+        hr = ICERR_UNSUPPORTED;
       if (lpbiIn->biHeight != lpbiOut->biHeight)
-       hr = ICERR_UNSUPPORTED;
+        hr = ICERR_UNSUPPORTED;
       if (lpbiIn->biBitCount > lpbiOut->biBitCount)
-       hr = ICERR_UNSUPPORTED;
+        hr = ICERR_UNSUPPORTED;
     }
   }
 
@@ -1648,49 +1658,57 @@ static LRESULT DecompressBegin(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn,
   if (pi->bDecompress)
     DecompressEnd(pi);
 
-  rgbIn  = (const RGBQUAD*)((const BYTE*)lpbiIn  + lpbiIn->biSize);
-  rgbOut = (const RGBQUAD*)((const BYTE*)lpbiOut + lpbiOut->biSize);
-
-  switch (lpbiOut->biBitCount) {
-  case 4:
-  case 8:
-    pi->palette_map = LocalAlloc(LPTR, lpbiIn->biClrUsed);
-    if (pi->palette_map == NULL)
-      return ICERR_MEMORY;
+  if (lpbiIn->biCompression != BI_RGB)
+  {
+    int colors;
 
-    for (i = 0; i < lpbiIn->biClrUsed; i++) {
-      pi->palette_map[i] = MSRLE32_GetNearestPaletteIndex(lpbiOut->biClrUsed, rgbOut, rgbIn[i]);
-    }
-    break;
-  case 15:
-  case 16:
-    pi->palette_map = LocalAlloc(LPTR, lpbiIn->biClrUsed * 2);
-    if (pi->palette_map == NULL)
-      return ICERR_MEMORY;
+    if (lpbiIn->biBitCount <= 8 && lpbiIn->biClrUsed == 0)
+      colors = 1 << lpbiIn->biBitCount;
+    else
+      colors = lpbiIn->biClrUsed;
 
-    for (i = 0; i < lpbiIn->biClrUsed; i++) {
-      WORD color;
+    rgbIn  = (const RGBQUAD*)((const BYTE*)lpbiIn  + lpbiIn->biSize);
+    rgbOut = (const RGBQUAD*)((const BYTE*)lpbiOut + lpbiOut->biSize);
 
-      if (lpbiOut->biBitCount == 15)
-       color = ((rgbIn[i].rgbRed >> 3) << 10)
-         | ((rgbIn[i].rgbGreen >> 3) << 5) | (rgbIn[i].rgbBlue >> 3);
-      else
-       color = ((rgbIn[i].rgbRed >> 3) << 11)
-         | ((rgbIn[i].rgbGreen >> 3) << 5) | (rgbIn[i].rgbBlue >> 3);
+    switch (lpbiOut->biBitCount) {
+    case 4:
+    case 8:
+      pi->palette_map = LocalAlloc(LPTR, colors);
+      if (pi->palette_map == NULL)
+        return ICERR_MEMORY;
 
-      pi->palette_map[i * 2 + 1] = color >> 8;
-      pi->palette_map[i * 2 + 0] = color & 0xFF;
+      for (i = 0; i < colors; i++)
+        pi->palette_map[i] = MSRLE32_GetNearestPaletteIndex(colors, rgbOut, rgbIn[i]);
+      break;
+    case 15:
+    case 16:
+      pi->palette_map = LocalAlloc(LPTR, colors * 2);
+      if (pi->palette_map == NULL)
+        return ICERR_MEMORY;
+
+      for (i = 0; i < colors; i++) {
+        WORD color;
+
+        if (lpbiOut->biBitCount == 15)
+    color = ((rgbIn[i].rgbRed >> 3) << 10)
+      | ((rgbIn[i].rgbGreen >> 3) << 5) | (rgbIn[i].rgbBlue >> 3);
+        else
+    color = ((rgbIn[i].rgbRed >> 3) << 11)
+      | ((rgbIn[i].rgbGreen >> 3) << 5) | (rgbIn[i].rgbBlue >> 3);
+
+        pi->palette_map[i * 2 + 1] = color >> 8;
+        pi->palette_map[i * 2 + 0] = color & 0xFF;
+      };
+      break;
+    case 24:
+    case 32:
+      pi->palette_map = LocalAlloc(LPTR, colors * sizeof(RGBQUAD));
+      if (pi->palette_map == NULL)
+        return ICERR_MEMORY;
+      memcpy(pi->palette_map, rgbIn, colors * sizeof(RGBQUAD));
+      break;
     };
-    break;
-  case 24:
-  case 32:
-    pi->palette_map = LocalAlloc(LPTR, lpbiIn->biClrUsed * sizeof(RGBQUAD));
-    if (pi->palette_map == NULL)
-      return ICERR_MEMORY;
-    memcpy(pi->palette_map, rgbIn, lpbiIn->biClrUsed * sizeof(RGBQUAD));
-    break;
-  };
-
+  }
   pi->bDecompress = TRUE;
 
   return ICERR_OK;
@@ -1721,6 +1739,14 @@ static LRESULT Decompress(CodecInfo *pi, ICDECOMPRESS *pic, DWORD dwSize)
   assert(pic->lpbiInput->biWidth  == pic->lpbiOutput->biWidth);
   assert(pic->lpbiInput->biHeight == pic->lpbiOutput->biHeight);
 
+  /* Uncompressed frame? */
+  if (pic->lpbiInput->biCompression == BI_RGB)
+  {
+    pic->lpbiOutput->biSizeImage = pic->lpbiInput->biSizeImage;
+    memcpy(pic->lpOutput, pic->lpInput, pic->lpbiOutput->biSizeImage);
+    return ICERR_OK;
+  }
+
   pic->lpbiOutput->biSizeImage = DIBWIDTHBYTES(*pic->lpbiOutput) * pic->lpbiOutput->biHeight;
   if (pic->lpbiInput->biBitCount == 4)
     return MSRLE32_DecompressRLE4(pi, pic->lpbiOutput, pic->lpInput, pic->lpOutput);