#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);
#define compare_fourcc(fcc1, fcc2) (((fcc1)^(fcc2))&~0x20202020)
-#define ABS(a) ((a) < 0 ? -(a) : (a))
-#define SQR(a) ((a) * (a))
-
-#define QUALITY_to_DIST(q) (ICQUALITY_HIGH - q)
static inline WORD ColorCmp(WORD clr1, WORD clr2)
{
- register UINT a = (clr1-clr2);
- return SQR(a);
+ UINT a = clr1 - clr2;
+ return a * a;
}
static inline WORD Intensity(RGBQUAD clr)
{
}
size = (2 + a * (2 + ((a + 2) & ~2)) + b * (2 + ((b + 2) & ~2)));
- return size * lpbi->biHeight;
+ return size * lpbi->biHeight + 2;
}
/* lpP => current pos in previous frame
static INT MSRLE32_CompressRLE8Line(const CodecInfo *pi, const WORD *lpP,
const WORD *lpC, LPCBITMAPINFOHEADER lpbi,
- const BYTE *lpIn, LONG lDist,
- INT x, LPBYTE *ppOut,
+ const BYTE *lpIn, INT x, LPBYTE *ppOut,
DWORD *lpSizeImage)
{
LPBYTE lpOut = *ppOut;
pos = x;
clr = lpC[pos++];
for (count = 1; pos < lpbi->biWidth; count++) {
- if (ColorCmp(clr, lpC[pos++]) > lDist)
+ if (ColorCmp(clr, lpC[pos++]) > 0)
break;
}
if (count < 2) {
/* add some more pixels for absoluting if possible */
- count += countDiffRLE8(lpP, lpC - 1, lpC, pos-1, lDist, lpbi->biWidth);
+ count += countDiffRLE8(lpP, lpC - 1, lpC, pos-1, 0, lpbi->biWidth);
assert(count > 0);
LPBYTE lpOut, BOOL isKey)
{
LPWORD lpC;
- LONG lLine, lInLine, lDist;
+ LONG lLine, lInLine;
LPBYTE lpOutStart = lpOut;
/* pre-conditions */
assert(pi->pCurFrame != NULL);
lpC = pi->pCurFrame;
- lDist = QUALITY_to_DIST(pi->dwQuality);
lInLine = DIBWIDTHBYTES(*lpbiIn);
lLine = WIDTHBYTES(lpbiOut->biWidth * 16) / 2;
x = 0;
do {
- x = MSRLE32_CompressRLE4Line(pi, NULL, lpC, lpbiIn, lpIn, lDist, x,
+ x = MSRLE32_CompressRLE4Line(pi, NULL, lpC, lpbiIn, lpIn, 0, x,
&lpOut, &lpbiOut->biSizeImage);
} while (x < lpbiOut->biWidth);
if (jumpx == -1)
jumpx = x;
for (count = 0, pos = x; pos < lpbiOut->biWidth; pos++, count++) {
- if (ColorCmp(lpP[pos], lpC[pos]) > lDist)
+ if (ColorCmp(lpP[pos], lpC[pos]) > 0)
break;
}
if (x < lpbiOut->biWidth) {
/* skipped the 'same' things corresponding to previous frame */
- x = MSRLE32_CompressRLE4Line(pi, lpP, lpC, lpbiIn, lpIn, lDist, x,
+ x = MSRLE32_CompressRLE4Line(pi, lpP, lpC, lpbiIn, lpIn, 0, x,
&lpOut, &lpbiOut->biSizeImage);
}
} while (x < lpbiOut->biWidth);
LPBYTE lpOut, BOOL isKey)
{
LPWORD lpC;
- LONG lDist, lInLine, lLine;
+ LONG lInLine, lLine;
LPBYTE lpOutStart = lpOut;
assert(pi != NULL && lpbiOut != NULL);
assert(pi->pCurFrame != NULL);
lpC = pi->pCurFrame;
- lDist = QUALITY_to_DIST(pi->dwQuality);
lInLine = DIBWIDTHBYTES(*lpbiIn);
lLine = WIDTHBYTES(lpbiOut->biWidth * 16) / 2;
x = 0;
do {
- x = MSRLE32_CompressRLE8Line(pi, NULL, lpC, lpbiIn, lpIn, lDist, x,
+ x = MSRLE32_CompressRLE8Line(pi, NULL, lpC, lpbiIn, lpIn, x,
&lpOut, &lpbiOut->biSizeImage);
assert(lpOut == (lpOutStart + lpbiOut->biSizeImage));
} while (x < lpbiOut->biWidth);
if (jumpx == -1)
jumpx = x;
for (count = 0, pos = x; pos < lpbiOut->biWidth; pos++, count++) {
- if (ColorCmp(lpP[pos], lpC[pos]) > lDist)
+ if (ColorCmp(lpP[pos], lpC[pos]) > 0)
break;
}
if (x < lpbiOut->biWidth) {
/* skip the 'same' things corresponding to previous frame */
- x = MSRLE32_CompressRLE8Line(pi, lpP, lpC, lpbiIn, lpIn, lDist, x,
+ x = MSRLE32_CompressRLE8Line(pi, lpP, lpC, lpbiIn, lpIn, x,
&lpOut, &lpbiOut->biSizeImage);
assert(lpOut == (lpOutStart + lpbiOut->biSizeImage));
}
}
}
- /* add EOL -- will be changed to EOI */
+ /* add EOL */
lpbiOut->biSizeImage += 2;
*((LPWORD)lpOut) = 0;
lpOut += sizeof(WORD);
}
- /* change EOL to EOI -- end of image */
- lpOut[-1] = 1;
+ /* add EOI -- end of image */
+ lpbiOut->biSizeImage += 2;
+ *lpOut++ = 0;
+ *lpOut++ = 1;
assert(lpOut == (lpOutStart + lpbiOut->biSizeImage));
return ICERR_OK;
pi->fccHandler = icinfo->fccHandler;
pi->bCompress = FALSE;
- pi->dwQuality = MSRLE32_DEFAULTQUALITY;
pi->nPrevFrame = -1;
pi->pPrevFrame = pi->pCurFrame = NULL;
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);
}
-static LRESULT SetQuality(CodecInfo *pi, LONG lQuality)
-{
- /* pre-condition */
- assert(pi != NULL);
-
- if (lQuality == -1)
- lQuality = MSRLE32_DEFAULTQUALITY;
- else if (ICQUALITY_LOW > lQuality || lQuality > ICQUALITY_HIGH)
- return ICERR_BADPARAM;
-
- pi->dwQuality = (DWORD)lQuality;
-
- return ICERR_OK;
-}
-
static LRESULT Configure(const CodecInfo *pi, HWND hWnd)
{
/* pre-condition */
/* 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);
static LRESULT Compress(CodecInfo *pi, ICCOMPRESS* lpic, DWORD dwSize)
{
+ BOOL is_key;
int i;
TRACE("(%p,%p,%u)\n",pi,lpic,dwSize);
computeInternalFrame(pi, lpic->lpbiPrev, lpic->lpPrev);
/* swap buffers for current and previous frame */
- /* Don't free and alloc new -- costs to much time and they are of equal size ! */
+ /* Don't free and alloc new -- costs too much time and they are of equal size ! */
pTmp = pi->pPrevFrame;
pi->pPrevFrame = pi->pCurFrame;
pi->pCurFrame = pTmp;
pi->nPrevFrame = lpic->lFrameNum;
}
- for (i = 0; i < 3; i++) {
- SetQuality(pi, lpic->dwQuality);
+ is_key = (lpic->dwFlags & ICCOMPRESS_KEYFRAME) != 0;
+ for (i = 0; i < 3; i++) {
lpic->lpbiOutput->biSizeImage = 0;
if (lpic->lpbiOutput->biBitCount == 4)
- MSRLE32_CompressRLE4(pi, lpic->lpbiInput, lpic->lpInput,
- lpic->lpbiOutput, lpic->lpOutput, (lpic->dwFlags & ICCOMPRESS_KEYFRAME) != 0);
+ MSRLE32_CompressRLE4(pi, lpic->lpbiInput, lpic->lpInput, lpic->lpbiOutput, lpic->lpOutput, is_key);
else
- MSRLE32_CompressRLE8(pi, lpic->lpbiInput, lpic->lpInput,
- lpic->lpbiOutput, lpic->lpOutput, (lpic->dwFlags & ICCOMPRESS_KEYFRAME) != 0);
+ MSRLE32_CompressRLE8(pi, lpic->lpbiInput, lpic->lpInput, lpic->lpbiOutput, lpic->lpOutput, is_key);
if (lpic->dwFrameSize == 0 ||
lpic->lpbiOutput->biSizeImage < lpic->dwFrameSize)
if (lpic->dwFrameSize == 0 ||
lpic->lpbiOutput->biSizeImage < lpic->dwFrameSize) {
WARN("switched to keyframe, was small enough!\n");
- *lpic->lpdwFlags |= ICCOMPRESS_KEYFRAME;
+ is_key = TRUE;
*lpic->lpckid = MAKEAVICKID(cktypeDIBbits,
StreamFromFOURCC(*lpic->lpckid));
break;
}
{ /* swap buffer for current and previous frame */
- /* Don't free and alloc new -- costs to much time and they are of equal size ! */
- register LPWORD pTmp = pi->pPrevFrame;
+ /* Don't free and alloc new -- costs too much time and they are of equal size ! */
+ LPWORD pTmp = pi->pPrevFrame;
pi->pPrevFrame = pi->pCurFrame;
pi->pCurFrame = pTmp;
pi->nPrevFrame = lpic->lFrameNum;
}
+ /* FIXME: What is AVIIF_TWOCC? */
+ *lpic->lpdwFlags |= AVIIF_TWOCC | (is_key ? AVIIF_KEYFRAME : 0);
return ICERR_OK;
}
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;
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);
/* check input format if given */
if (lpbiIn != NULL) {
- if (!isSupportedMRLE(lpbiIn))
+ if (!isSupportedMRLE(lpbiIn) && !isSupportedDIB(lpbiIn))
return ICERR_BADFORMAT;
}
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;
}
}
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;
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);
return ICERR_OK;
}
break;
- case ICM_GETQUALITY:
- if ((LPVOID)lParam1 != NULL) {
- *((LPDWORD)lParam1) = pi->dwQuality;
- return ICERR_OK;
- }
- break;
- case ICM_SETQUALITY:
- return SetQuality(pi, *(LPLONG)lParam1);
case ICM_COMPRESS_GET_FORMAT:
return CompressGetFormat(pi, (LPCBITMAPINFOHEADER)lParam1,
(LPBITMAPINFOHEADER)lParam2);
DisableThreadLibraryCalls(hModule);
MSRLE32_hModule = hModule;
break;
-
- case DLL_PROCESS_DETACH:
- break;
}
return TRUE;