mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
@@ -25,6 +25,7 @@
|
||||
#include <winpr/cast.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/config.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/codec/bitmap.h>
|
||||
|
||||
@@ -38,20 +39,6 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
static inline BYTE PLANAR_CONTROL_BYTE(UINT32 nRunLength, UINT32 cRawBytes)
|
||||
{
|
||||
return WINPR_ASSERTING_INT_CAST(UINT8, ((nRunLength & 0x0F) | ((cRawBytes & 0x0F) << 4)));
|
||||
}
|
||||
|
||||
static inline BYTE PLANAR_CONTROL_BYTE_RUN_LENGTH(UINT32 controlByte)
|
||||
{
|
||||
return (controlByte & 0x0F);
|
||||
}
|
||||
static inline BYTE PLANAR_CONTROL_BYTE_RAW_BYTES(UINT32 controlByte)
|
||||
{
|
||||
return ((controlByte >> 4) & 0x0F);
|
||||
}
|
||||
|
||||
typedef struct S_BITMAP_PLANAR_CONTEXT BITMAP_PLANAR_CONTEXT;
|
||||
|
||||
FREERDP_API BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT context,
|
||||
@@ -74,12 +61,21 @@ extern "C"
|
||||
FREERDP_API void freerdp_planar_topdown_image(BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT planar,
|
||||
BOOL topdown);
|
||||
|
||||
FREERDP_API BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT planar,
|
||||
const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize,
|
||||
UINT32 nSrcWidth, UINT32 nSrcHeight,
|
||||
BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,
|
||||
UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
|
||||
UINT32 nDstWidth, UINT32 nDstHeight, BOOL vFlip);
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
WINPR_DEPRECATED_VAR("use freerdp_bitmap_decompress_planar instead",
|
||||
FREERDP_API BOOL planar_decompress(
|
||||
BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT planar,
|
||||
const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize, UINT32 nSrcWidth,
|
||||
UINT32 nSrcHeight, BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,
|
||||
UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT32 nDstWidth,
|
||||
UINT32 nDstHeight, BOOL vFlip));
|
||||
#endif
|
||||
|
||||
FREERDP_API BOOL freerdp_bitmap_decompress_planar(
|
||||
BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT planar, const BYTE* WINPR_RESTRICT pSrcData,
|
||||
UINT32 SrcSize, UINT32 nSrcWidth, UINT32 nSrcHeight, BYTE* WINPR_RESTRICT pDstData,
|
||||
UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT32 nDstWidth,
|
||||
UINT32 nDstHeight, BOOL vFlip);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -96,10 +96,24 @@ struct S_BITMAP_PLANAR_CONTEXT
|
||||
BOOL topdown;
|
||||
};
|
||||
|
||||
static inline BYTE PLANAR_CONTROL_BYTE(UINT32 nRunLength, UINT32 cRawBytes)
|
||||
{
|
||||
return WINPR_ASSERTING_INT_CAST(UINT8, ((nRunLength & 0x0F) | ((cRawBytes & 0x0F) << 4)));
|
||||
}
|
||||
|
||||
static inline BYTE PLANAR_CONTROL_BYTE_RUN_LENGTH(UINT32 controlByte)
|
||||
{
|
||||
return (controlByte & 0x0F);
|
||||
}
|
||||
static inline BYTE PLANAR_CONTROL_BYTE_RAW_BYTES(UINT32 controlByte)
|
||||
{
|
||||
return ((controlByte >> 4) & 0x0F);
|
||||
}
|
||||
|
||||
static INLINE UINT32 planar_invert_format(BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT planar, BOOL alpha,
|
||||
UINT32 DstFormat)
|
||||
{
|
||||
|
||||
WINPR_ASSERT(planar);
|
||||
if (planar->bgr && alpha)
|
||||
{
|
||||
switch (DstFormat)
|
||||
@@ -361,8 +375,6 @@ static INLINE INT32 planar_decompress_plane_rle(const BYTE* WINPR_RESTRICT pSrcD
|
||||
WINPR_ASSERT(nWidth <= INT32_MAX);
|
||||
WINPR_ASSERT(nDstStep <= INT32_MAX);
|
||||
|
||||
previousScanline = NULL;
|
||||
|
||||
if (vFlip)
|
||||
{
|
||||
beg = (INT32)nHeight - 1;
|
||||
@@ -486,8 +498,8 @@ static INLINE INT32 planar_set_plane(BYTE bValue, BYTE* pDstData, UINT32 nDstSte
|
||||
BOOL vFlip)
|
||||
{
|
||||
INT32 beg = 0;
|
||||
INT32 end = 0;
|
||||
INT32 inc = 0;
|
||||
INT32 end = (INT32)nHeight;
|
||||
INT32 inc = 1;
|
||||
|
||||
WINPR_ASSERT(nHeight <= INT32_MAX);
|
||||
WINPR_ASSERT(nWidth <= INT32_MAX);
|
||||
@@ -499,12 +511,6 @@ static INLINE INT32 planar_set_plane(BYTE bValue, BYTE* pDstData, UINT32 nDstSte
|
||||
end = -1;
|
||||
inc = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
beg = 0;
|
||||
end = (INT32)nHeight;
|
||||
inc = 1;
|
||||
}
|
||||
|
||||
for (INT32 y = beg; y != end; y += inc)
|
||||
{
|
||||
@@ -687,11 +693,25 @@ static BOOL planar_subsample_expand(const BYTE* WINPR_RESTRICT plane, size_t pla
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT planar,
|
||||
const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize, UINT32 nSrcWidth,
|
||||
UINT32 nSrcHeight, BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,
|
||||
UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT32 nDstWidth,
|
||||
UINT32 nDstHeight, BOOL vFlip)
|
||||
{
|
||||
return freerdp_bitmap_decompress_planar(planar, pSrcData, SrcSize, nSrcWidth, nSrcHeight,
|
||||
pDstData, DstFormat, nDstStep, nXDst, nYDst, nDstWidth,
|
||||
nDstHeight, vFlip);
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOL freerdp_bitmap_decompress_planar(BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT planar,
|
||||
const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize,
|
||||
UINT32 nSrcWidth, UINT32 nSrcHeight,
|
||||
BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,
|
||||
UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT32 nDstWidth,
|
||||
UINT32 nDstHeight, BOOL vFlip)
|
||||
{
|
||||
BOOL useAlpha = FALSE;
|
||||
INT32 status = 0;
|
||||
@@ -1155,12 +1175,10 @@ static INLINE UINT32 freerdp_bitmap_planar_write_rle_bytes(const BYTE* WINPR_RES
|
||||
BYTE* WINPR_RESTRICT pOutBuffer,
|
||||
UINT32 outBufferSize)
|
||||
{
|
||||
const BYTE* pInput = NULL;
|
||||
BYTE* pOutput = NULL;
|
||||
const BYTE* pInput = pInBuffer;
|
||||
BYTE* pOutput = pOutBuffer;
|
||||
BYTE controlByte = 0;
|
||||
UINT32 nBytesToWrite = 0;
|
||||
pInput = pInBuffer;
|
||||
pOutput = pOutBuffer;
|
||||
|
||||
if (!cRawBytes && !nRunLength)
|
||||
return 0;
|
||||
@@ -1274,20 +1292,13 @@ static INLINE UINT32 freerdp_bitmap_planar_encode_rle_bytes(const BYTE* WINPR_RE
|
||||
UINT32 outBufferSize)
|
||||
{
|
||||
BYTE symbol = 0;
|
||||
const BYTE* pInput = NULL;
|
||||
BYTE* pOutput = NULL;
|
||||
const BYTE* pInput = pInBuffer;
|
||||
BYTE* pOutput = pOutBuffer;
|
||||
const BYTE* pBytes = NULL;
|
||||
UINT32 cRawBytes = 0;
|
||||
UINT32 nRunLength = 0;
|
||||
UINT32 bSymbolMatch = 0;
|
||||
UINT32 nBytesWritten = 0;
|
||||
UINT32 nTotalBytesWritten = 0;
|
||||
symbol = 0;
|
||||
cRawBytes = 0;
|
||||
nRunLength = 0;
|
||||
pInput = pInBuffer;
|
||||
pOutput = pOutBuffer;
|
||||
nTotalBytesWritten = 0;
|
||||
|
||||
if (!outBufferSize)
|
||||
return 0;
|
||||
@@ -1297,7 +1308,7 @@ static INLINE UINT32 freerdp_bitmap_planar_encode_rle_bytes(const BYTE* WINPR_RE
|
||||
if (!inBufferSize)
|
||||
break;
|
||||
|
||||
bSymbolMatch = (symbol == *pInput) ? TRUE : FALSE;
|
||||
const UINT32 bSymbolMatch = (symbol == *pInput) ? TRUE : FALSE;
|
||||
symbol = *pInput;
|
||||
pInput++;
|
||||
inBufferSize--;
|
||||
@@ -1352,25 +1363,18 @@ BOOL freerdp_bitmap_planar_compress_plane_rle(const BYTE* WINPR_RESTRICT inPlane
|
||||
UINT32 height, BYTE* WINPR_RESTRICT outPlane,
|
||||
UINT32* WINPR_RESTRICT dstSize)
|
||||
{
|
||||
UINT32 index = 0;
|
||||
const BYTE* pInput = NULL;
|
||||
BYTE* pOutput = NULL;
|
||||
UINT32 outBufferSize = 0;
|
||||
UINT32 nBytesWritten = 0;
|
||||
UINT32 nTotalBytesWritten = 0;
|
||||
|
||||
if (!outPlane)
|
||||
return FALSE;
|
||||
|
||||
index = 0;
|
||||
pInput = inPlane;
|
||||
pOutput = outPlane;
|
||||
outBufferSize = *dstSize;
|
||||
nTotalBytesWritten = 0;
|
||||
UINT32 index = 0;
|
||||
const BYTE* pInput = inPlane;
|
||||
BYTE* pOutput = outPlane;
|
||||
UINT32 outBufferSize = *dstSize;
|
||||
UINT32 nTotalBytesWritten = 0;
|
||||
|
||||
while (outBufferSize)
|
||||
while (outBufferSize > 0)
|
||||
{
|
||||
nBytesWritten =
|
||||
const UINT32 nBytesWritten =
|
||||
freerdp_bitmap_planar_encode_rle_bytes(pInput, width, pOutput, outBufferSize);
|
||||
|
||||
if ((!nBytesWritten) || (nBytesWritten > outBufferSize))
|
||||
@@ -1446,35 +1450,33 @@ static INLINE BOOL freerdp_bitmap_planar_compress_planes_rle(BYTE* WINPR_RESTRIC
|
||||
BYTE* freerdp_bitmap_planar_delta_encode_plane(const BYTE* WINPR_RESTRICT inPlane, UINT32 width,
|
||||
UINT32 height, BYTE* WINPR_RESTRICT outPlane)
|
||||
{
|
||||
BYTE* outPtr = NULL;
|
||||
const BYTE* srcPtr = NULL;
|
||||
const BYTE* prevLinePtr = NULL;
|
||||
|
||||
if (!outPlane)
|
||||
{
|
||||
if (width * height == 0)
|
||||
return NULL;
|
||||
|
||||
if (!(outPlane = (BYTE*)calloc(height, width)))
|
||||
outPlane = (BYTE*)calloc(height, width);
|
||||
if (!outPlane)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// first line is copied as is
|
||||
CopyMemory(outPlane, inPlane, width);
|
||||
outPtr = outPlane + width;
|
||||
srcPtr = inPlane + width;
|
||||
prevLinePtr = inPlane;
|
||||
|
||||
for (UINT32 y = 1; y < height; y++)
|
||||
{
|
||||
for (UINT32 x = 0; x < width; x++, outPtr++, srcPtr++, prevLinePtr++)
|
||||
const size_t off = 1ull * width * y;
|
||||
BYTE* outPtr = &outPlane[off];
|
||||
const BYTE* srcPtr = &inPlane[off];
|
||||
const BYTE* prevLinePtr = &inPlane[off - width];
|
||||
for (UINT32 x = 0; x < width; x++)
|
||||
{
|
||||
const INT32 delta = *srcPtr - *prevLinePtr;
|
||||
const int s2c1i = (delta >= 0) ? delta : (~((BYTE)(-delta)) + 1);
|
||||
const char s2c1 = WINPR_CXX_COMPAT_CAST(char, s2c1i & 0xff);
|
||||
const uint32_t s2c = (s2c1 >= 0) ? ((UINT32)s2c1 << 1)
|
||||
: (((UINT32)(~((BYTE)(s2c1 & 0xFF)) + 1) << 1) - 1);
|
||||
*outPtr = (BYTE)s2c;
|
||||
const int delta = (int)srcPtr[x] - (int)prevLinePtr[x];
|
||||
const int s2c1i = (delta >= 0) ? delta : (INT_MAX + delta) + 1;
|
||||
const int8_t s2c1 = WINPR_CXX_COMPAT_CAST(int8_t, s2c1i);
|
||||
const uint32_t s2c =
|
||||
(s2c1 >= 0) ? ((UINT32)s2c1 << 1) : (((UINT32)(~(s2c1) + 1) << 1) - 1);
|
||||
outPtr[x] = (BYTE)s2c;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1504,7 +1506,6 @@ BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT conte
|
||||
{
|
||||
UINT32 size = 0;
|
||||
BYTE* dstp = NULL;
|
||||
UINT32 planeSize = 0;
|
||||
UINT32 dstSizes[4] = { 0 };
|
||||
BYTE FormatHeader = 0;
|
||||
|
||||
@@ -1514,7 +1515,7 @@ BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT conte
|
||||
if (context->AllowSkipAlpha)
|
||||
FormatHeader |= PLANAR_FORMAT_HEADER_NA;
|
||||
|
||||
planeSize = width * height;
|
||||
const UINT32 planeSize = width * height;
|
||||
|
||||
if (!context->AllowSkipAlpha)
|
||||
format = planar_invert_format(context, TRUE, format);
|
||||
|
||||
@@ -171,7 +171,7 @@ static void* read_data(const char* type, const char* name, size_t* plength)
|
||||
cmp = NULL;
|
||||
|
||||
fail:
|
||||
(void)printf("%s: %s %s -> %p\n", __func__, type, name, cmp);
|
||||
(void)printf("%s: %s %s -> %p\n", __func__, type, name, rc);
|
||||
free(cmp);
|
||||
if (fp)
|
||||
(void)fclose(fp);
|
||||
@@ -199,9 +199,18 @@ static BOOL compare(const char* type, const char* name, const void* data, size_t
|
||||
if (!cmp)
|
||||
goto fail;
|
||||
if (cmplen != length)
|
||||
{
|
||||
(void)printf("%s: %s %s: length mismatch: %" PRIuz " vs %" PRIuz "\n", __func__, type, name,
|
||||
cmplen, length);
|
||||
goto fail;
|
||||
}
|
||||
if (memcmp(data, cmp, length) != 0)
|
||||
{
|
||||
(void)printf("%s: %s %s: data mismatch\n", __func__, type, name);
|
||||
winpr_HexDump(__func__, WLOG_WARN, data, length);
|
||||
winpr_HexDump(__func__, WLOG_WARN, cmp, cmplen);
|
||||
goto fail;
|
||||
}
|
||||
rc = TRUE;
|
||||
fail:
|
||||
(void)printf("%s: %s %s -> %s\n", __func__, type, name, rc ? "SUCCESS" : "FAILED");
|
||||
@@ -228,10 +237,6 @@ static BOOL RunTestPlanar(BITMAP_PLANAR_CONTEXT* encplanar, BITMAP_PLANAR_CONTEX
|
||||
BYTE* decompressedBitmap =
|
||||
(BYTE*)calloc(height, 1ULL * width * FreeRDPGetBytesPerPixel(dstFormat));
|
||||
|
||||
if (!compare("bmp", name, srcBitmap,
|
||||
1ull * width * height * FreeRDPGetBytesPerPixel(srcFormat)))
|
||||
goto fail;
|
||||
|
||||
if (!compare("enc", name, compressedBitmap, dstSize))
|
||||
goto fail;
|
||||
|
||||
@@ -241,8 +246,9 @@ static BOOL RunTestPlanar(BITMAP_PLANAR_CONTEXT* encplanar, BITMAP_PLANAR_CONTEX
|
||||
if (!compressedBitmap || !decompressedBitmap)
|
||||
goto fail;
|
||||
|
||||
if (!planar_decompress(decplanar, compressedBitmap, dstSize, width, height, decompressedBitmap,
|
||||
dstFormat, 0, 0, 0, width, height, FALSE))
|
||||
if (!freerdp_bitmap_decompress_planar(decplanar, compressedBitmap, dstSize, width, height,
|
||||
decompressedBitmap, dstFormat, 0, 0, 0, width, height,
|
||||
FALSE))
|
||||
{
|
||||
(void)printf("failed to decompress experimental bitmap 01: width: %" PRIu32
|
||||
" height: %" PRIu32 "\n",
|
||||
@@ -321,8 +327,9 @@ static BOOL RunTestPlanarSingleColor(BITMAP_PLANAR_CONTEXT* planar, const UINT32
|
||||
if (!compressedBitmap)
|
||||
goto fail_loop;
|
||||
|
||||
if (!planar_decompress(planar, compressedBitmap, compressedSize, width, height,
|
||||
decompressedBitmap, dstFormat, 0, 0, 0, width, height, FALSE))
|
||||
if (!freerdp_bitmap_decompress_planar(planar, compressedBitmap, compressedSize, width,
|
||||
height, decompressedBitmap, dstFormat, 0, 0, 0,
|
||||
width, height, FALSE))
|
||||
goto fail_loop;
|
||||
|
||||
if (!CompareBitmap(decompressedBitmap, dstFormat, bmp, srcFormat, width, height))
|
||||
@@ -494,9 +501,9 @@ static BOOL FuzzPlanar(void)
|
||||
FreeRDPGetColorFormatName(DstFormat), nXDst, nYDst, nDstWidth, nDstHeight, nDstStep,
|
||||
sizeof(dstData));
|
||||
freerdp_planar_switch_bgr(planar, ((prand(2) % 2) != 0) ? TRUE : FALSE);
|
||||
planar_decompress(planar, data, dataSize, prand(4096), prand(4096), dstData, DstFormat,
|
||||
nDstStep, nXDst, nYDst, nDstWidth, nDstHeight,
|
||||
((prand(2) % 2) != 0) ? TRUE : FALSE);
|
||||
freerdp_bitmap_decompress_planar(planar, data, dataSize, prand(4096), prand(4096), dstData,
|
||||
DstFormat, nDstStep, nXDst, nYDst, nDstWidth, nDstHeight,
|
||||
((prand(2) % 2) != 0) ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
|
||||
@@ -1324,9 +1324,9 @@ static int test_dump(int argc, char* argv[])
|
||||
{
|
||||
const UINT64 start = winpr_GetTickCount64NS();
|
||||
|
||||
if (!planar_decompress(codecs->planar, cmd.data, cmd.length, cmd.width,
|
||||
cmd.height, dst, DstFormat, stride, cmd.left, cmd.top,
|
||||
cmd.width, cmd.height, FALSE))
|
||||
if (!freerdp_bitmap_decompress_planar(
|
||||
codecs->planar, cmd.data, cmd.length, cmd.width, cmd.height, dst,
|
||||
DstFormat, stride, cmd.left, cmd.top, cmd.width, cmd.height, FALSE))
|
||||
success = -1;
|
||||
|
||||
const RECTANGLE_16 invalidRect = { .left = (UINT16)MIN(UINT16_MAX, cmd.left),
|
||||
|
||||
@@ -540,9 +540,10 @@ static UINT gdi_SurfaceCommand_Planar(rdpGdi* gdi, RdpgfxClientContext* context,
|
||||
if (!is_within_surface(surface, cmd))
|
||||
return ERROR_INVALID_DATA;
|
||||
|
||||
if (!planar_decompress(surface->codecs->planar, cmd->data, cmd->length, cmd->width, cmd->height,
|
||||
DstData, surface->format, surface->scanline, cmd->left, cmd->top,
|
||||
cmd->width, cmd->height, FALSE))
|
||||
if (!freerdp_bitmap_decompress_planar(surface->codecs->planar, cmd->data, cmd->length,
|
||||
cmd->width, cmd->height, DstData, surface->format,
|
||||
surface->scanline, cmd->left, cmd->top, cmd->width,
|
||||
cmd->height, FALSE))
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
invalidRect.left = (UINT16)MIN(UINT16_MAX, cmd->left);
|
||||
|
||||
@@ -206,11 +206,11 @@ static BOOL gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, const
|
||||
const BOOL fidelity =
|
||||
freerdp_settings_get_bool(context->settings, FreeRDP_DrawAllowDynamicColorFidelity);
|
||||
freerdp_planar_switch_bgr(context->codecs->planar, fidelity);
|
||||
if (!planar_decompress(context->codecs->planar, pSrcData, SrcSize, DstWidth, DstHeight,
|
||||
bitmap->data, bitmap->format, 0, 0, 0, DstWidth, DstHeight,
|
||||
TRUE))
|
||||
if (!freerdp_bitmap_decompress_planar(context->codecs->planar, pSrcData, SrcSize,
|
||||
DstWidth, DstHeight, bitmap->data, bitmap->format,
|
||||
0, 0, 0, DstWidth, DstHeight, TRUE))
|
||||
{
|
||||
WLog_ERR(TAG, "planar_decompress failed");
|
||||
WLog_ERR(TAG, "freerdp_bitmap_decompress_planar failed");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user