From 9eeb64ed9f8dc852a26c3d693a6d9a18eccc12f5 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 12 Jan 2021 09:41:09 +0100 Subject: [PATCH] Ignore alpha channel during color conversion. Most GFX graphics do not carry alpha data. Keep the original alpha value unless specified otherwise. (cherry picked from commit 115532ef5a71676a946c9d268dd1294daf99e52d) --- include/freerdp/codec/color.h | 21 ++++++ libfreerdp/primitives/prim_YCoCg.c | 4 +- libfreerdp/primitives/prim_YUV.c | 16 ++--- libfreerdp/primitives/prim_YUV_ssse3.c | 4 +- libfreerdp/primitives/prim_colors.c | 10 +-- libfreerdp/primitives/prim_internal.h | 90 +++++++++++++++++++++++--- 6 files changed, 118 insertions(+), 27 deletions(-) diff --git a/include/freerdp/codec/color.h b/include/freerdp/codec/color.h index 127271c16..42cb104d1 100644 --- a/include/freerdp/codec/color.h +++ b/include/freerdp/codec/color.h @@ -809,6 +809,27 @@ extern "C" return TRUE; } + static INLINE BOOL WriteColorIgnoreAlpha(BYTE* dst, UINT32 format, UINT32 color) + { + switch (format) + { + case PIXEL_FORMAT_ABGR32: + case PIXEL_FORMAT_ARGB32: + { + const UINT32 tmp = (dst[0] << 24) | (color & 0x00FFFFFF); + return WriteColor(dst, format, tmp); + } + case PIXEL_FORMAT_BGRA32: + case PIXEL_FORMAT_RGBA32: + { + const UINT32 tmp = (dst[3]) | (color & 0xFFFFFF00); + return WriteColor(dst, format, tmp); + } + default: + return WriteColor(dst, format, color); + } + } + /*** * * Converts a pixel in internal representation format srcFormat to internal diff --git a/libfreerdp/primitives/prim_YCoCg.c b/libfreerdp/primitives/prim_YCoCg.c index 93d62b6f9..a3dc1f05b 100644 --- a/libfreerdp/primitives/prim_YCoCg.c +++ b/libfreerdp/primitives/prim_YCoCg.c @@ -37,7 +37,7 @@ static pstatus_t general_YCoCgToRGB_8u_AC4R(const BYTE* pSrc, INT32 srcStep, BYT const BYTE* sptr = pSrc; INT16 Cg, Co, Y, T, R, G, B; const DWORD formatSize = GetBytesPerPixel(DstFormat); - fkt_writePixel writePixel = getPixelWriteFunction(DstFormat); + fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, TRUE); int cll = shift - 1; /* -1 builds in the /2's */ UINT32 srcPad = srcStep - (width * 4); UINT32 dstPad = dstStep - (width * formatSize); @@ -59,7 +59,7 @@ static pstatus_t general_YCoCgToRGB_8u_AC4R(const BYTE* pSrc, INT32 srcStep, BYT B = T + Co; G = Y + Cg; R = T - Co; - dptr = (*writePixel)(dptr, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), A); + dptr = writePixel(dptr, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), A); } sptr += srcPad; diff --git a/libfreerdp/primitives/prim_YUV.c b/libfreerdp/primitives/prim_YUV.c index d6e0d3eeb..0bca4befe 100644 --- a/libfreerdp/primitives/prim_YUV.c +++ b/libfreerdp/primitives/prim_YUV.c @@ -385,7 +385,7 @@ static pstatus_t general_YUV444ToRGB_8u_P3AC4R_general(const BYTE* const pSrc[3] UINT32 x, y; UINT32 nWidth, nHeight; const DWORD formatSize = GetBytesPerPixel(DstFormat); - fkt_writePixel writePixel = getPixelWriteFunction(DstFormat); + fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE); nWidth = roi->width; nHeight = roi->height; @@ -404,7 +404,7 @@ static pstatus_t general_YUV444ToRGB_8u_P3AC4R_general(const BYTE* const pSrc[3] const BYTE r = YUV2R(Y, U, V); const BYTE g = YUV2G(Y, U, V); const BYTE b = YUV2B(Y, U, V); - pRGB = (*writePixel)(pRGB, formatSize, DstFormat, r, g, b, 0xFF); + pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0); } } @@ -437,7 +437,7 @@ static pstatus_t general_YUV444ToRGB_8u_P3AC4R_BGRX(const BYTE* const pSrc[3], const BYTE r = YUV2R(Y, U, V); const BYTE g = YUV2G(Y, U, V); const BYTE b = YUV2B(Y, U, V); - pRGB = writePixelBGRX(pRGB, formatSize, DstFormat, r, g, b, 0xFF); + pRGB = writePixelBGRX(pRGB, formatSize, DstFormat, r, g, b, 0); } } @@ -481,7 +481,7 @@ static pstatus_t general_YUV420ToRGB_8u_P3AC4R(const BYTE* const pSrc[3], const UINT32 nWidth, nHeight; UINT32 lastRow, lastCol; const DWORD formatSize = GetBytesPerPixel(DstFormat); - fkt_writePixel writePixel = getPixelWriteFunction(DstFormat); + fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE); pY = pSrc[0]; pU = pSrc[1]; pV = pSrc[2]; @@ -517,7 +517,7 @@ static pstatus_t general_YUV420ToRGB_8u_P3AC4R(const BYTE* const pSrc[3], const r = YUV2R(Y, U, V); g = YUV2G(Y, U, V); b = YUV2B(Y, U, V); - pRGB = (*writePixel)(pRGB, formatSize, DstFormat, r, g, b, 0xFF); + pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0); /* 2nd pixel */ if (!(lastCol & 0x02)) @@ -526,7 +526,7 @@ static pstatus_t general_YUV420ToRGB_8u_P3AC4R(const BYTE* const pSrc[3], const r = YUV2R(Y, U, V); g = YUV2G(Y, U, V); b = YUV2B(Y, U, V); - pRGB = (*writePixel)(pRGB, formatSize, DstFormat, r, g, b, 0xFF); + pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0); } else { @@ -560,7 +560,7 @@ static pstatus_t general_YUV420ToRGB_8u_P3AC4R(const BYTE* const pSrc[3], const r = YUV2R(Y, U, V); g = YUV2G(Y, U, V); b = YUV2B(Y, U, V); - pRGB = (*writePixel)(pRGB, formatSize, DstFormat, r, g, b, 0xFF); + pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0); /* 4th pixel */ if (!(lastCol & 0x02)) @@ -569,7 +569,7 @@ static pstatus_t general_YUV420ToRGB_8u_P3AC4R(const BYTE* const pSrc[3], const r = YUV2R(Y, U, V); g = YUV2G(Y, U, V); b = YUV2B(Y, U, V); - pRGB = (*writePixel)(pRGB, formatSize, DstFormat, r, g, b, 0xFF); + pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0); } else { diff --git a/libfreerdp/primitives/prim_YUV_ssse3.c b/libfreerdp/primitives/prim_YUV_ssse3.c index 45c820933..8c8fa962f 100644 --- a/libfreerdp/primitives/prim_YUV_ssse3.c +++ b/libfreerdp/primitives/prim_YUV_ssse3.c @@ -191,7 +191,7 @@ static pstatus_t ssse3_YUV420ToRGB_BGRX(const BYTE* const* pSrc, const UINT32* s const BYTE r = YUV2R(Y, U, V); const BYTE g = YUV2G(Y, U, V); const BYTE b = YUV2B(Y, U, V); - dst = (__m128i*)writePixelBGRX((BYTE*)dst, 4, PIXEL_FORMAT_BGRX32, r, g, b, 0xFF); + dst = (__m128i*)writePixelBGRX((BYTE*)dst, 4, PIXEL_FORMAT_BGRX32, r, g, b, 0); if (x % 2) { @@ -257,7 +257,7 @@ static pstatus_t ssse3_YUV444ToRGB_8u_P3AC4R_BGRX(const BYTE* const* pSrc, const const BYTE r = YUV2R(Y, U, V); const BYTE g = YUV2G(Y, U, V); const BYTE b = YUV2B(Y, U, V); - dst = (__m128i*)writePixelBGRX((BYTE*)dst, 4, PIXEL_FORMAT_BGRX32, r, g, b, 0xFF); + dst = (__m128i*)writePixelBGRX((BYTE*)dst, 4, PIXEL_FORMAT_BGRX32, r, g, b, 0); } } diff --git a/libfreerdp/primitives/prim_colors.c b/libfreerdp/primitives/prim_colors.c index 54c7ecbc9..ac9456f35 100644 --- a/libfreerdp/primitives/prim_colors.c +++ b/libfreerdp/primitives/prim_colors.c @@ -60,7 +60,7 @@ static pstatus_t general_yCbCrToRGB_16s8u_P3AC4R_BGRX(const INT16* const pSrc[3] R = ((INT16)((CrR + Y) >> divisor) >> 5); G = ((INT16)((Y - CbG - CrG) >> divisor) >> 5); B = ((INT16)((CbB + Y) >> divisor) >> 5); - pRGB = writePixelBGRX(pRGB, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), 0xFF); + pRGB = writePixelBGRX(pRGB, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), 0); } pY += srcPad; @@ -83,7 +83,7 @@ static pstatus_t general_yCbCrToRGB_16s8u_P3AC4R_general(const INT16* const pSrc const INT16* pCr = pSrc[2]; const size_t srcPad = (srcStep - (roi->width * 2)) / 2; const size_t dstPad = (dstStep - (roi->width * 4)); - const fkt_writePixel writePixel = getPixelWriteFunction(DstFormat); + const fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE); const DWORD formatSize = GetBytesPerPixel(DstFormat); for (y = 0; y < roi->height; y++) @@ -102,7 +102,7 @@ static pstatus_t general_yCbCrToRGB_16s8u_P3AC4R_general(const INT16* const pSrc R = (INT64)((CrR + Y) >> (divisor + 5)); G = (INT64)((Y - CbG - CrG) >> (divisor + 5)); B = (INT64)((CbB + Y) >> (divisor + 5)); - pRGB = (*writePixel)(pRGB, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), 0xFF); + pRGB = writePixel(pRGB, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), 0); } pY += srcPad; @@ -283,10 +283,10 @@ static INLINE void writeScanlineGeneric(BYTE* dst, DWORD formatSize, UINT32 DstF const INT16* r, const INT16* g, const INT16* b, DWORD width) { DWORD x; - fkt_writePixel writePixel = getPixelWriteFunction(DstFormat); + fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE); for (x = 0; x < width; x++) - dst = (*writePixel)(dst, formatSize, DstFormat, *r++, *g++, *b++, 0xFF); + dst = writePixel(dst, formatSize, DstFormat, *r++, *g++, *b++, 0); } static INLINE void writeScanlineRGB(BYTE* dst, DWORD formatSize, UINT32 DstFormat, const INT16* r, diff --git a/libfreerdp/primitives/prim_internal.h b/libfreerdp/primitives/prim_internal.h index f0ea9ce2f..a305f78d1 100644 --- a/libfreerdp/primitives/prim_internal.h +++ b/libfreerdp/primitives/prim_internal.h @@ -47,14 +47,43 @@ : _mm_load_si128((__m128i*)(_ptr_))) #endif +static INLINE BYTE* writePixelBGRA(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G, + BYTE B, BYTE A) +{ + WINPR_UNUSED(formatSize); + WINPR_UNUSED(format); + + *dst++ = B; + *dst++ = G; + *dst++ = R; + *dst++ = A; + return dst; +} + static INLINE BYTE* writePixelBGRX(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G, BYTE B, BYTE A) { WINPR_UNUSED(formatSize); WINPR_UNUSED(format); + WINPR_UNUSED(A); + *dst++ = B; *dst++ = G; *dst++ = R; + dst++; /* Do not touch alpha */ + + return dst; +} + +static INLINE BYTE* writePixelRGBA(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G, + BYTE B, BYTE A) +{ + WINPR_UNUSED(formatSize); + WINPR_UNUSED(format); + + *dst++ = R; + *dst++ = G; + *dst++ = B; *dst++ = A; return dst; } @@ -64,10 +93,26 @@ static INLINE BYTE* writePixelRGBX(BYTE* dst, DWORD formatSize, UINT32 format, B { WINPR_UNUSED(formatSize); WINPR_UNUSED(format); + WINPR_UNUSED(A); + *dst++ = R; *dst++ = G; *dst++ = B; + dst++; /* Do not touch alpha */ + + return dst; +} + +static INLINE BYTE* writePixelABGR(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G, + BYTE B, BYTE A) +{ + WINPR_UNUSED(formatSize); + WINPR_UNUSED(format); + *dst++ = A; + *dst++ = B; + *dst++ = G; + *dst++ = R; return dst; } @@ -76,57 +121,82 @@ static INLINE BYTE* writePixelXBGR(BYTE* dst, DWORD formatSize, UINT32 format, B { WINPR_UNUSED(formatSize); WINPR_UNUSED(format); - *dst++ = A; + WINPR_UNUSED(A); + + dst++; /* Do not touch alpha */ *dst++ = B; *dst++ = G; *dst++ = R; return dst; } +static INLINE BYTE* writePixelARGB(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G, + BYTE B, BYTE A) +{ + WINPR_UNUSED(formatSize); + WINPR_UNUSED(format); + + *dst++ = A; + *dst++ = R; + *dst++ = G; + *dst++ = B; + return dst; +} + static INLINE BYTE* writePixelXRGB(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G, BYTE B, BYTE A) { WINPR_UNUSED(formatSize); WINPR_UNUSED(format); - *dst++ = A; + WINPR_UNUSED(A); + + dst++; /* Do not touch alpha */ *dst++ = R; *dst++ = G; *dst++ = B; return dst; } -static INLINE BYTE* writePixelGeneric(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G, - BYTE B, BYTE A) +static INLINE BYTE* writePixelGenericAlpha(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, + BYTE G, BYTE B, BYTE A) { UINT32 color = FreeRDPGetColor(format, R, G, B, A); WriteColor(dst, format, color); return dst + formatSize; } +static INLINE BYTE* writePixelGeneric(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G, + BYTE B, BYTE A) +{ + UINT32 color = FreeRDPGetColor(format, R, G, B, A); + WriteColorIgnoreAlpha(dst, format, color); + return dst + formatSize; +} + typedef BYTE* (*fkt_writePixel)(BYTE*, DWORD, UINT32, BYTE, BYTE, BYTE, BYTE); -static INLINE fkt_writePixel getPixelWriteFunction(DWORD format) +static INLINE fkt_writePixel getPixelWriteFunction(DWORD format, BOOL useAlpha) { switch (format) { case PIXEL_FORMAT_ARGB32: case PIXEL_FORMAT_XRGB32: - return writePixelXRGB; + return useAlpha ? writePixelARGB : writePixelXRGB; case PIXEL_FORMAT_ABGR32: case PIXEL_FORMAT_XBGR32: - return writePixelXBGR; + return useAlpha ? writePixelABGR : writePixelXBGR; case PIXEL_FORMAT_RGBA32: case PIXEL_FORMAT_RGBX32: - return writePixelRGBX; + return useAlpha ? writePixelRGBA : writePixelRGBX; case PIXEL_FORMAT_BGRA32: case PIXEL_FORMAT_BGRX32: - return writePixelBGRX; + return useAlpha ? writePixelBGRA : writePixelBGRX; default: - return writePixelGeneric; + return useAlpha ? writePixelGenericAlpha : writePixelGeneric; } }