mirror of https://github.com/FreeRDP/FreeRDP
Merge pull request #4276 from akallabeth/big_endian_more
Big endian fixes
This commit is contained in:
commit
f6b8a6eaa2
|
@ -3,6 +3,8 @@
|
|||
* NCrush (RDP6) Bulk Data Compression
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2017 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2017 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -30,7 +32,7 @@
|
|||
|
||||
#define TAG FREERDP_TAG("codec")
|
||||
|
||||
UINT16 HuffTableLEC[8192] =
|
||||
static const UINT16 HuffTableLEC[8192] =
|
||||
{
|
||||
0x510B, 0x611F, 0x610D, 0x9027, 0x6000, 0x7105, 0x6117, 0xA068, 0x5111, 0x7007, 0x6113, 0x90C0, 0x6108, 0x8018, 0x611B, 0xA0B3,
|
||||
0x510F, 0x7003, 0x6110, 0x9042, 0x6002, 0x800B, 0x6119, 0xA091, 0x5121, 0x7080, 0x6115, 0xA03A, 0x610A, 0x9012, 0x611D, 0xA0D7,
|
||||
|
@ -546,7 +548,7 @@ UINT16 HuffTableLEC[8192] =
|
|||
0x510F, 0x7006, 0x6112, 0x9090, 0x6107, 0x8013, 0x611A, 0xA0B1, 0x5121, 0x7103, 0x6116, 0xA067, 0x610C, 0x9026, 0x611E, 0xD125
|
||||
};
|
||||
|
||||
UINT16 HuffTableLOM[512] =
|
||||
static const UINT16 HuffTableLOM[512] =
|
||||
{
|
||||
0x2001, 0x4000, 0x3002, 0x4008, 0x2001, 0x4005, 0x3004, 0x500A, 0x2001, 0x4003, 0x3002, 0x5007, 0x2001, 0x4006, 0x3004, 0x700D,
|
||||
0x2001, 0x4000, 0x3002, 0x4008, 0x2001, 0x4005, 0x3004, 0x600B, 0x2001, 0x4003, 0x3002, 0x5009, 0x2001, 0x4006, 0x3004, 0x8012,
|
||||
|
@ -582,7 +584,7 @@ UINT16 HuffTableLOM[512] =
|
|||
0x2001, 0x4000, 0x3002, 0x4008, 0x2001, 0x4005, 0x3004, 0x600C, 0x2001, 0x4003, 0x3002, 0x5009, 0x2001, 0x4006, 0x3004, 0x901F
|
||||
};
|
||||
|
||||
const BYTE HuffTableMask[39] =
|
||||
static const BYTE HuffTableMask[39] =
|
||||
{
|
||||
0x11, /* 0 */
|
||||
0x9E, /* 1 */
|
||||
|
@ -625,7 +627,7 @@ const BYTE HuffTableMask[39] =
|
|||
0x00 /* 38 */
|
||||
};
|
||||
|
||||
const BYTE HuffLengthLEC[294] =
|
||||
static const BYTE HuffLengthLEC[294] =
|
||||
{
|
||||
6, /* 0 */
|
||||
6, /* 1 */
|
||||
|
@ -923,7 +925,7 @@ const BYTE HuffLengthLEC[294] =
|
|||
13 /* 293 */
|
||||
};
|
||||
|
||||
const BYTE HuffCodeLEC[588] =
|
||||
static const BYTE HuffCodeLEC[588] =
|
||||
{
|
||||
0x04, /* 0 */
|
||||
0x00, /* 1 */
|
||||
|
@ -1515,7 +1517,7 @@ const BYTE HuffCodeLEC[588] =
|
|||
0x1F /* 587 */
|
||||
};
|
||||
|
||||
const BYTE HuffLengthLOM[32] =
|
||||
static const BYTE HuffLengthLOM[32] =
|
||||
{
|
||||
4, /* 0 */
|
||||
2, /* 1 */
|
||||
|
@ -1551,7 +1553,7 @@ const BYTE HuffLengthLOM[32] =
|
|||
9 /* 31 */
|
||||
};
|
||||
|
||||
const UINT16 HuffCodeLOM[32] =
|
||||
static const UINT16 HuffCodeLOM[32] =
|
||||
{
|
||||
0x0001, /* 0 */
|
||||
0x0000, /* 1 */
|
||||
|
@ -1587,7 +1589,7 @@ const UINT16 HuffCodeLOM[32] =
|
|||
0x01FF /* 31 */
|
||||
};
|
||||
|
||||
UINT32 CopyOffsetBitsLUT[32] =
|
||||
static const UINT32 CopyOffsetBitsLUT[32] =
|
||||
{
|
||||
0x0, /* 0 */
|
||||
0x0, /* 1 */
|
||||
|
@ -1623,7 +1625,7 @@ UINT32 CopyOffsetBitsLUT[32] =
|
|||
0xE /* 31 */
|
||||
};
|
||||
|
||||
UINT32 CopyOffsetBaseLUT[32] =
|
||||
static const UINT32 CopyOffsetBaseLUT[32] =
|
||||
{
|
||||
0x1, /* 0 */
|
||||
0x2, /* 1 */
|
||||
|
@ -1659,7 +1661,7 @@ UINT32 CopyOffsetBaseLUT[32] =
|
|||
0xC001 /* 31 */
|
||||
};
|
||||
|
||||
UINT32 LOMBitsLUT[30] =
|
||||
static const UINT32 LOMBitsLUT[30] =
|
||||
{
|
||||
0x0, /* 0 */
|
||||
0x0, /* 1 */
|
||||
|
@ -1693,7 +1695,7 @@ UINT32 LOMBitsLUT[30] =
|
|||
0xE /* 29 */
|
||||
};
|
||||
|
||||
UINT32 LOMBaseLUT[30] =
|
||||
static const UINT32 LOMBaseLUT[30] =
|
||||
{
|
||||
0x2, /* 0 */
|
||||
0x3, /* 1 */
|
||||
|
@ -1727,51 +1729,89 @@ UINT32 LOMBaseLUT[30] =
|
|||
0x2 /* 29 */
|
||||
};
|
||||
|
||||
#define NCrushFetchBits() \
|
||||
if (nbits < 16) { \
|
||||
if ((SrcPtr + 1) >= SrcEnd) { \
|
||||
if (SrcPtr >= SrcEnd) { \
|
||||
if (nbits < 0) \
|
||||
return -1; \
|
||||
} else { \
|
||||
bits += *SrcPtr++ << nbits; \
|
||||
nbits += 8; \
|
||||
} \
|
||||
} else { \
|
||||
bits += *((UINT16*) SrcPtr) << nbits; \
|
||||
SrcPtr += 2; \
|
||||
nbits += 16; \
|
||||
} \
|
||||
} \
|
||||
static INLINE UINT16 get_word(const BYTE* data)
|
||||
{
|
||||
UINT16 tmp = *data++;
|
||||
tmp |= *data << 8;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#define NCrushWriteStart() \
|
||||
bits = 0; \
|
||||
offset = 0; \
|
||||
accumulator = 0
|
||||
static INLINE UINT32 get_dword(const BYTE* data)
|
||||
{
|
||||
UINT32 tmp = *data++;
|
||||
tmp |= *data++ << 8U;
|
||||
tmp |= *data++ << 16U;
|
||||
tmp |= *data++ << 24U;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#define NCrushWriteBits(_bits, _nbits) \
|
||||
accumulator |= _bits << offset; \
|
||||
offset += _nbits; \
|
||||
if (offset >= 16) { \
|
||||
*DstPtr++ = accumulator & 0xFF; \
|
||||
*DstPtr++ = (accumulator >> 8) & 0xFF; \
|
||||
accumulator >>= 16; \
|
||||
offset -= 16; \
|
||||
static INLINE BOOL NCrushFetchBits(const BYTE** SrcPtr, const BYTE** SrcEnd, INT32* nbits,
|
||||
UINT32* bits)
|
||||
{
|
||||
if (*nbits < 16)
|
||||
{
|
||||
if ((*SrcPtr + 1) >= *SrcEnd)
|
||||
{
|
||||
if (*SrcPtr >= *SrcEnd)
|
||||
{
|
||||
if (*nbits < 0)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*bits += *(*SrcPtr)++ << *nbits;
|
||||
*nbits += 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT16 tmp = *(*SrcPtr)++;
|
||||
tmp |= (*(*SrcPtr)++) << 8;
|
||||
*bits += tmp << *nbits;
|
||||
*nbits += 16;
|
||||
}
|
||||
}
|
||||
|
||||
#define NCrushWriteFinish() \
|
||||
*DstPtr++ = accumulator & 0xFF; \
|
||||
*DstPtr++ = (accumulator >> 8) & 0xFF
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags)
|
||||
static INLINE void NCrushWriteStart(UINT32* bits, UINT32* offset, UINT32* accumulator)
|
||||
{
|
||||
*bits = 0;
|
||||
*offset = 0;
|
||||
*accumulator = 0;
|
||||
}
|
||||
|
||||
static INLINE void NCrushWriteBits(BYTE** DstPtr, UINT32* accumulator, UINT32* offset,
|
||||
UINT32 _bits, UINT32 _nbits)
|
||||
{
|
||||
*accumulator |= _bits << *offset;
|
||||
*offset += _nbits;
|
||||
|
||||
if (*offset >= 16)
|
||||
{
|
||||
*(*DstPtr)++ = (*accumulator & 0xFF);
|
||||
*(*DstPtr)++ = ((*accumulator >> 8) & 0xFF);
|
||||
*accumulator >>= 16;
|
||||
*offset -= 16;
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE void NCrushWriteFinish(BYTE** DstPtr, UINT32 accumulator)
|
||||
{
|
||||
*(*DstPtr)++ = accumulator & 0xFF;
|
||||
*(*DstPtr)++ = (accumulator >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData,
|
||||
UINT32* pDstSize, UINT32 flags)
|
||||
{
|
||||
UINT32 index;
|
||||
UINT32 bits;
|
||||
INT32 nbits;
|
||||
BYTE* SrcPtr;
|
||||
BYTE* SrcEnd;
|
||||
const BYTE* SrcPtr;
|
||||
const BYTE* SrcEnd;
|
||||
UINT16 Mask;
|
||||
UINT16* pMask;
|
||||
BYTE Literal;
|
||||
UINT32 IndexLEC;
|
||||
UINT32 BitLength;
|
||||
|
@ -1824,26 +1864,23 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
|
|||
}
|
||||
|
||||
SrcEnd = &pSrcData[SrcSize];
|
||||
|
||||
nbits = 32;
|
||||
bits = *((UINT32*) pSrcData);
|
||||
bits = get_dword(pSrcData);
|
||||
SrcPtr = pSrcData + 4;
|
||||
|
||||
while (1)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
pMask = (UINT16*) &HuffTableMask[29];
|
||||
Mask = *pMask;
|
||||
Mask = get_word(&HuffTableMask[29]);
|
||||
MaskedBits = bits & Mask;
|
||||
|
||||
IndexLEC = HuffTableLEC[MaskedBits] & 0xFFF;
|
||||
BitLength = HuffTableLEC[MaskedBits] >> 12;
|
||||
|
||||
bits >>= BitLength;
|
||||
nbits -= BitLength;
|
||||
|
||||
NCrushFetchBits();
|
||||
if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits))
|
||||
return -1;
|
||||
|
||||
if (IndexLEC >= 256)
|
||||
break;
|
||||
|
@ -1856,7 +1893,6 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
|
|||
}
|
||||
|
||||
Literal = (HuffTableLEC[MaskedBits] & 0xFF);
|
||||
|
||||
*HistoryPtr++ = Literal;
|
||||
}
|
||||
|
||||
|
@ -1873,34 +1909,29 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
|
|||
return -1004;
|
||||
|
||||
CopyOffset = ncrush->OffsetCache[OffsetCacheIndex];
|
||||
|
||||
pMask = (UINT16*) &HuffTableMask[21];
|
||||
Mask = *pMask;
|
||||
Mask = get_word(&HuffTableMask[21]);
|
||||
MaskedBits = bits & Mask;
|
||||
|
||||
LengthOfMatch = HuffTableLOM[MaskedBits] & 0xFFF;
|
||||
BitLength = HuffTableLOM[MaskedBits] >> 12;
|
||||
|
||||
bits >>= BitLength;
|
||||
nbits -= BitLength;
|
||||
|
||||
NCrushFetchBits();
|
||||
if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits))
|
||||
return -1;
|
||||
|
||||
LengthOfMatchBits = LOMBitsLUT[LengthOfMatch];
|
||||
LengthOfMatchBase = LOMBaseLUT[LengthOfMatch];
|
||||
|
||||
if (LengthOfMatchBits)
|
||||
{
|
||||
pMask = (UINT16*) &HuffTableMask[(2 * LengthOfMatchBits) + 3];
|
||||
Mask = *pMask;
|
||||
Mask = get_word(&HuffTableMask[(2 * LengthOfMatchBits) + 3]);
|
||||
MaskedBits = bits & Mask;
|
||||
|
||||
bits >>= LengthOfMatchBits;
|
||||
nbits -= LengthOfMatchBits;
|
||||
|
||||
LengthOfMatchBase += MaskedBits;
|
||||
|
||||
NCrushFetchBits();
|
||||
if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits))
|
||||
return -1;
|
||||
}
|
||||
|
||||
OldCopyOffset = ncrush->OffsetCache[OffsetCacheIndex];
|
||||
|
@ -1915,45 +1946,39 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
|
|||
|
||||
if (CopyOffsetBits)
|
||||
{
|
||||
pMask = (UINT16*) &HuffTableMask[(2 * CopyOffsetBits) + 3];
|
||||
Mask = *pMask;
|
||||
Mask = get_word(&HuffTableMask[(2 * CopyOffsetBits) + 3]);
|
||||
MaskedBits = bits & Mask;
|
||||
|
||||
CopyOffset = CopyOffsetBase + MaskedBits - 1;
|
||||
|
||||
bits >>= CopyOffsetBits;
|
||||
nbits -= CopyOffsetBits;
|
||||
|
||||
NCrushFetchBits();
|
||||
if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits))
|
||||
return -1;
|
||||
}
|
||||
|
||||
pMask = (UINT16*) &HuffTableMask[21];
|
||||
Mask = *pMask;
|
||||
Mask = get_word(&HuffTableMask[21]);
|
||||
MaskedBits = bits & Mask;
|
||||
|
||||
LengthOfMatch = HuffTableLOM[MaskedBits] & 0xFFF;
|
||||
BitLength = HuffTableLOM[MaskedBits] >> 12;
|
||||
|
||||
bits >>= BitLength;
|
||||
nbits -= BitLength;
|
||||
|
||||
NCrushFetchBits();
|
||||
if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits))
|
||||
return -1;
|
||||
|
||||
LengthOfMatchBits = LOMBitsLUT[LengthOfMatch];
|
||||
LengthOfMatchBase = LOMBaseLUT[LengthOfMatch];
|
||||
|
||||
if (LengthOfMatchBits)
|
||||
{
|
||||
pMask = (UINT16*) &HuffTableMask[(2 * LengthOfMatchBits) + 3];
|
||||
Mask = *pMask;
|
||||
Mask = get_word(&HuffTableMask[(2 * LengthOfMatchBits) + 3]);
|
||||
MaskedBits = bits & Mask;
|
||||
|
||||
bits >>= LengthOfMatchBits;
|
||||
nbits -= LengthOfMatchBits;
|
||||
|
||||
LengthOfMatchBase += MaskedBits;
|
||||
|
||||
NCrushFetchBits();
|
||||
if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits))
|
||||
return -1;
|
||||
}
|
||||
|
||||
ncrush->OffsetCache[3] = ncrush->OffsetCache[2];
|
||||
|
@ -1973,7 +1998,6 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
|
|||
return -1006;
|
||||
|
||||
CopyOffsetPtr = HistoryPtr - CopyOffset;
|
||||
|
||||
index = 0;
|
||||
CopyLength = (LengthOfMatch > CopyOffset) ? CopyOffset : LengthOfMatch;
|
||||
|
||||
|
@ -2024,32 +2048,32 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
|
|||
|
||||
if (ncrush->HistoryBufferFence != 0xABABABAB)
|
||||
{
|
||||
WLog_ERR(TAG, "NCrushDecompress: history buffer fence was overwritten, potential buffer overflow detected!");
|
||||
WLog_ERR(TAG,
|
||||
"NCrushDecompress: history buffer fence was overwritten, potential buffer overflow detected!");
|
||||
return -1007;
|
||||
}
|
||||
|
||||
*pDstSize = HistoryPtr - ncrush->HistoryPtr;
|
||||
*ppDstData = ncrush->HistoryPtr;
|
||||
ncrush->HistoryPtr = HistoryPtr;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ncrush_hash_table_add(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, UINT32 HistoryOffset)
|
||||
static int ncrush_hash_table_add(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSize,
|
||||
UINT32 HistoryOffset)
|
||||
{
|
||||
BYTE* SrcPtr;
|
||||
const BYTE* SrcPtr;
|
||||
UINT32 Hash;
|
||||
UINT32 Offset;
|
||||
UINT32 EndOffset;
|
||||
|
||||
SrcPtr = pSrcData;
|
||||
Offset = HistoryOffset;
|
||||
EndOffset = Offset + SrcSize - 8;
|
||||
|
||||
while (Offset < EndOffset)
|
||||
{
|
||||
Hash = ncrush->HashTable[*((UINT16*) SrcPtr)];
|
||||
ncrush->HashTable[*((UINT16*) SrcPtr)] = Offset;
|
||||
Hash = ncrush->HashTable[get_word(SrcPtr)];
|
||||
ncrush->HashTable[get_word(SrcPtr)] = Offset;
|
||||
ncrush->MatchTable[Offset] = Hash;
|
||||
SrcPtr++;
|
||||
Offset++;
|
||||
|
@ -2058,10 +2082,10 @@ int ncrush_hash_table_add(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize
|
|||
return 1;
|
||||
}
|
||||
|
||||
int ncrush_find_match_length(BYTE* Ptr1, BYTE* Ptr2, BYTE* HistoryPtr)
|
||||
static int ncrush_find_match_length(const BYTE* Ptr1, const BYTE* Ptr2, BYTE* HistoryPtr)
|
||||
{
|
||||
BYTE val1, val2;
|
||||
BYTE* Ptr = Ptr1;
|
||||
const BYTE* Ptr = Ptr1;
|
||||
|
||||
do
|
||||
{
|
||||
|
@ -2076,7 +2100,8 @@ int ncrush_find_match_length(BYTE* Ptr1, BYTE* Ptr2, BYTE* HistoryPtr)
|
|||
return Ptr1 - (Ptr + 1);
|
||||
}
|
||||
|
||||
int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset, UINT32* pMatchOffset)
|
||||
static int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset,
|
||||
UINT32* pMatchOffset)
|
||||
{
|
||||
int i, j;
|
||||
int Length;
|
||||
|
@ -2093,10 +2118,8 @@ int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset, UINT32*
|
|||
MatchLength = 2;
|
||||
Offset = HistoryOffset;
|
||||
HistoryBuffer = (BYTE*) ncrush->HistoryBuffer;
|
||||
|
||||
ncrush->MatchTable[0] = HistoryOffset;
|
||||
MatchOffset = ncrush->MatchTable[HistoryOffset];
|
||||
|
||||
NextOffset = ncrush->MatchTable[Offset];
|
||||
MatchPtr = &HistoryBuffer[MatchLength];
|
||||
|
||||
|
@ -2107,6 +2130,7 @@ int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset, UINT32*
|
|||
if (j < 0)
|
||||
{
|
||||
Offset = ncrush->MatchTable[NextOffset];
|
||||
|
||||
if (MatchPtr[NextOffset] == HistoryBuffer[HistoryOffset + MatchLength])
|
||||
j = 0;
|
||||
}
|
||||
|
@ -2114,6 +2138,7 @@ int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset, UINT32*
|
|||
if (j < 0)
|
||||
{
|
||||
NextOffset = ncrush->MatchTable[Offset];
|
||||
|
||||
if (MatchPtr[Offset] == HistoryBuffer[HistoryOffset + MatchLength])
|
||||
j = 1;
|
||||
}
|
||||
|
@ -2121,6 +2146,7 @@ int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset, UINT32*
|
|||
if (j < 0)
|
||||
{
|
||||
Offset = ncrush->MatchTable[NextOffset];
|
||||
|
||||
if (MatchPtr[NextOffset] == HistoryBuffer[HistoryOffset + MatchLength])
|
||||
j = 2;
|
||||
}
|
||||
|
@ -2128,6 +2154,7 @@ int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset, UINT32*
|
|||
if (j < 0)
|
||||
{
|
||||
NextOffset = ncrush->MatchTable[Offset];
|
||||
|
||||
if (MatchPtr[Offset] == HistoryBuffer[HistoryOffset + MatchLength])
|
||||
j = 3;
|
||||
}
|
||||
|
@ -2135,6 +2162,7 @@ int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset, UINT32*
|
|||
if (j < 0)
|
||||
{
|
||||
Offset = ncrush->MatchTable[NextOffset];
|
||||
|
||||
if (MatchPtr[NextOffset] == HistoryBuffer[HistoryOffset + MatchLength])
|
||||
j = 4;
|
||||
}
|
||||
|
@ -2142,6 +2170,7 @@ int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset, UINT32*
|
|||
if (j < 0)
|
||||
{
|
||||
NextOffset = ncrush->MatchTable[Offset];
|
||||
|
||||
if (MatchPtr[Offset] == HistoryBuffer[HistoryOffset + MatchLength])
|
||||
j = 5;
|
||||
}
|
||||
|
@ -2175,17 +2204,17 @@ int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset, UINT32*
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ncrush->MatchTable[0] = 0;
|
||||
*pMatchOffset = MatchOffset;
|
||||
|
||||
return MatchLength;
|
||||
}
|
||||
|
||||
int ncrush_move_encoder_windows(NCRUSH_CONTEXT* ncrush, BYTE* HistoryPtr)
|
||||
static int ncrush_move_encoder_windows(NCRUSH_CONTEXT* ncrush, BYTE* HistoryPtr)
|
||||
{
|
||||
int i, j;
|
||||
int NewHash;
|
||||
|
@ -2205,13 +2234,10 @@ int ncrush_move_encoder_windows(NCRUSH_CONTEXT* ncrush, BYTE* HistoryPtr)
|
|||
{
|
||||
NewHash = ncrush->HashTable[i + 0] - HistoryOffset;
|
||||
ncrush->HashTable[i + 0] = (NewHash <= 0) ? 0 : NewHash;
|
||||
|
||||
NewHash = ncrush->HashTable[i + 1] - HistoryOffset;
|
||||
ncrush->HashTable[i + 1] = (NewHash <= 0) ? 0 : NewHash;
|
||||
|
||||
NewHash = ncrush->HashTable[i + 2] - HistoryOffset;
|
||||
ncrush->HashTable[i + 2] = (NewHash <= 0) ? 0 : NewHash;
|
||||
|
||||
NewHash = ncrush->HashTable[i + 3] - HistoryOffset;
|
||||
ncrush->HashTable[i + 3] = (NewHash <= 0) ? 0 : NewHash;
|
||||
}
|
||||
|
@ -2220,33 +2246,30 @@ int ncrush_move_encoder_windows(NCRUSH_CONTEXT* ncrush, BYTE* HistoryPtr)
|
|||
{
|
||||
NewMatch = ncrush->MatchTable[HistoryOffset + j + 0] - HistoryOffset;
|
||||
ncrush->MatchTable[j + 0] = (NewMatch <= 0) ? 0 : NewMatch;
|
||||
|
||||
NewMatch = ncrush->MatchTable[HistoryOffset + j + 1] - HistoryOffset;
|
||||
ncrush->MatchTable[j + 1] = (NewMatch <= 0) ? 0 : NewMatch;
|
||||
|
||||
NewMatch = ncrush->MatchTable[HistoryOffset + j + 2] - HistoryOffset;
|
||||
ncrush->MatchTable[j + 2] = (NewMatch <= 0) ? 0 : NewMatch;
|
||||
|
||||
NewMatch = ncrush->MatchTable[HistoryOffset + j + 3] - HistoryOffset;
|
||||
ncrush->MatchTable[j + 3] = (NewMatch <= 0) ? 0 : NewMatch;
|
||||
}
|
||||
|
||||
ZeroMemory(&ncrush->MatchTable[32768], 65536);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags)
|
||||
int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData,
|
||||
UINT32* pDstSize, UINT32* pFlags)
|
||||
{
|
||||
BYTE Literal;
|
||||
BYTE* SrcPtr;
|
||||
const BYTE* SrcPtr;
|
||||
BYTE* DstPtr;
|
||||
UINT32 bits;
|
||||
UINT32 offset;
|
||||
UINT16 Mask;
|
||||
UINT32 MaskedBits;
|
||||
UINT32 accumulator;
|
||||
BYTE* SrcEndPtr;
|
||||
const BYTE* SrcEndPtr;
|
||||
BYTE* DstEndPtr;
|
||||
BYTE* HistoryPtr;
|
||||
BYTE* pDstData;
|
||||
|
@ -2258,7 +2281,6 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
|
|||
UINT32 IndexLOM;
|
||||
UINT32 IndexCO;
|
||||
UINT32 CodeLEC;
|
||||
UINT16* pCodeLEC;
|
||||
UINT32 BitLength;
|
||||
UINT32 CopyOffset;
|
||||
UINT32 MatchOffset;
|
||||
|
@ -2272,10 +2294,8 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
|
|||
UINT32 CopyOffsetIndex;
|
||||
UINT32 CopyOffsetBits;
|
||||
UINT32 CompressionLevel;
|
||||
|
||||
CompressionLevel = 2;
|
||||
HistoryBuffer = ncrush->HistoryBuffer;
|
||||
|
||||
*pFlags = 0;
|
||||
PacketFlushed = FALSE;
|
||||
PacketAtFront = FALSE;
|
||||
|
@ -2315,9 +2335,7 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
|
|||
return -1003;
|
||||
|
||||
DstSize = SrcSize;
|
||||
|
||||
NCrushWriteStart();
|
||||
|
||||
NCrushWriteStart(&bits, &offset, &accumulator);
|
||||
DstPtr = pDstData;
|
||||
SrcPtr = pSrcData;
|
||||
SrcEndPtr = &pSrcData[SrcSize];
|
||||
|
@ -2326,7 +2344,6 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
|
|||
HistoryPtr = &HistoryBuffer[ncrush->HistoryOffset];
|
||||
HistoryBufferEndPtr = &HistoryBuffer[65536];
|
||||
HistoryBufferSize = ncrush->HistoryBufferSize;
|
||||
|
||||
CopyOffset = 0;
|
||||
MatchOffset = 0;
|
||||
ncrush_hash_table_add(ncrush, pSrcData, SrcSize, HistoryPtr - HistoryBuffer);
|
||||
|
@ -2362,7 +2379,6 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
|
|||
if (!MatchLength)
|
||||
{
|
||||
/* Literal */
|
||||
|
||||
Literal = *SrcPtr++;
|
||||
HistoryPtr++;
|
||||
|
||||
|
@ -2378,13 +2394,12 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
|
|||
|
||||
IndexLEC = Literal;
|
||||
BitLength = HuffLengthLEC[IndexLEC];
|
||||
pCodeLEC = (UINT16*) &HuffCodeLEC[IndexLEC * 2];
|
||||
CodeLEC = (UINT32) *pCodeLEC;
|
||||
CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]);
|
||||
|
||||
if (BitLength > 15)
|
||||
return -1006;
|
||||
|
||||
NCrushWriteBits(CodeLEC, BitLength);
|
||||
NCrushWriteBits(&DstPtr, &accumulator, &offset, CodeLEC, BitLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2455,7 +2470,6 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
|
|||
if (OffsetCacheIndex >= 4)
|
||||
{
|
||||
/* CopyOffset not in OffsetCache */
|
||||
|
||||
if (CopyOffset >= 256)
|
||||
bits = (CopyOffset >> 7) + 256;
|
||||
else
|
||||
|
@ -2463,11 +2477,9 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
|
|||
|
||||
CopyOffsetIndex = ncrush->HuffTableCopyOffset[bits + 2];
|
||||
CopyOffsetBits = CopyOffsetBitsLUT[CopyOffsetIndex];
|
||||
|
||||
IndexLEC = 257 + CopyOffsetIndex;
|
||||
BitLength = HuffLengthLEC[IndexLEC];
|
||||
pCodeLEC = (UINT16*) &HuffCodeLEC[IndexLEC * 2];
|
||||
CodeLEC = (UINT32) *pCodeLEC;
|
||||
CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]);
|
||||
|
||||
if (BitLength > 15)
|
||||
return -1008;
|
||||
|
@ -2475,12 +2487,10 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
|
|||
if (CopyOffsetBits > 18)
|
||||
return -1009;
|
||||
|
||||
NCrushWriteBits(CodeLEC, BitLength);
|
||||
|
||||
NCrushWriteBits(&DstPtr, &accumulator, &offset, CodeLEC, BitLength);
|
||||
Mask = ((1 << CopyOffsetBits) - 1);
|
||||
MaskedBits = CopyOffset & Mask;
|
||||
|
||||
NCrushWriteBits(MaskedBits, CopyOffsetBits);
|
||||
NCrushWriteBits(&DstPtr, &accumulator, &offset, MaskedBits, CopyOffsetBits);
|
||||
|
||||
if ((MatchLength - 2) >= 768)
|
||||
IndexCO = 28;
|
||||
|
@ -2489,13 +2499,10 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
|
|||
|
||||
BitLength = HuffLengthLOM[IndexCO];
|
||||
IndexLOM = LOMBitsLUT[IndexCO];
|
||||
|
||||
NCrushWriteBits(HuffCodeLOM[IndexCO], BitLength);
|
||||
|
||||
NCrushWriteBits(&DstPtr, &accumulator, &offset, HuffCodeLOM[IndexCO], BitLength);
|
||||
Mask = ((1 << IndexLOM) - 1);
|
||||
MaskedBits = (MatchLength - 2) & Mask;
|
||||
|
||||
NCrushWriteBits(MaskedBits, IndexLOM);
|
||||
NCrushWriteBits(&DstPtr, &accumulator, &offset, MaskedBits, IndexLOM);
|
||||
|
||||
if ((MaskedBits + LOMBaseLUT[IndexCO]) != MatchLength)
|
||||
return -1010;
|
||||
|
@ -2503,16 +2510,14 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
|
|||
else
|
||||
{
|
||||
/* CopyOffset in OffsetCache */
|
||||
|
||||
IndexLEC = 289 + OffsetCacheIndex;
|
||||
BitLength = HuffLengthLEC[IndexLEC];
|
||||
pCodeLEC = (UINT16*) &HuffCodeLEC[IndexLEC * 2];
|
||||
CodeLEC = (UINT32) *pCodeLEC;
|
||||
CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]);
|
||||
|
||||
if (BitLength >= 15)
|
||||
return -1011;
|
||||
|
||||
NCrushWriteBits(CodeLEC, BitLength);
|
||||
NCrushWriteBits(&DstPtr, &accumulator, &offset, CodeLEC, BitLength);
|
||||
|
||||
if ((MatchLength - 2) >= 768)
|
||||
IndexCO = 28;
|
||||
|
@ -2521,13 +2526,10 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
|
|||
|
||||
BitLength = HuffLengthLOM[IndexCO];
|
||||
IndexLOM = LOMBitsLUT[IndexCO];
|
||||
|
||||
NCrushWriteBits(HuffCodeLOM[IndexCO], BitLength);
|
||||
|
||||
NCrushWriteBits(&DstPtr, &accumulator, &offset, HuffCodeLOM[IndexCO], BitLength);
|
||||
Mask = ((1 << IndexLOM) - 1);
|
||||
MaskedBits = (MatchLength - 2) & Mask;
|
||||
|
||||
NCrushWriteBits(MaskedBits, IndexLOM);
|
||||
NCrushWriteBits(&DstPtr, &accumulator, &offset, MaskedBits, IndexLOM);
|
||||
|
||||
if ((MaskedBits + LOMBaseLUT[IndexCO]) != MatchLength)
|
||||
return -1012;
|
||||
|
@ -2552,16 +2554,14 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
|
|||
|
||||
Literal = *SrcPtr++;
|
||||
HistoryPtr++;
|
||||
|
||||
IndexLEC = Literal;
|
||||
BitLength = HuffLengthLEC[IndexLEC];
|
||||
pCodeLEC = (UINT16*) &HuffCodeLEC[IndexLEC * 2];
|
||||
CodeLEC = (UINT32) *pCodeLEC;
|
||||
CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]);
|
||||
|
||||
if (BitLength > 15)
|
||||
return -1014;
|
||||
|
||||
NCrushWriteBits(CodeLEC, BitLength);
|
||||
NCrushWriteBits(&DstPtr, &accumulator, &offset, CodeLEC, BitLength);
|
||||
}
|
||||
|
||||
if ((DstPtr + 4) >= DstEndPtr) /* PACKET_FLUSH #4 */
|
||||
|
@ -2580,13 +2580,9 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
|
|||
if (BitLength > 15)
|
||||
return -1015;
|
||||
|
||||
pCodeLEC = (UINT16*) &HuffCodeLEC[IndexLEC * 2];
|
||||
bits = (UINT32) *pCodeLEC;
|
||||
|
||||
NCrushWriteBits(bits, BitLength);
|
||||
|
||||
NCrushWriteFinish();
|
||||
|
||||
bits = get_word(&HuffCodeLEC[IndexLEC * 2]);
|
||||
NCrushWriteBits(&DstPtr, &accumulator, &offset, bits, BitLength);
|
||||
NCrushWriteFinish(&DstPtr, accumulator);
|
||||
*pDstSize = DstPtr - pDstData;
|
||||
|
||||
if (*pDstSize > SrcSize)
|
||||
|
@ -2609,11 +2605,11 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
|
|||
return 1;
|
||||
}
|
||||
|
||||
int ncrush_generate_tables(NCRUSH_CONTEXT *context)
|
||||
static int ncrush_generate_tables(NCRUSH_CONTEXT* context)
|
||||
{
|
||||
int i, j, k, l;
|
||||
|
||||
k = 0;
|
||||
|
||||
for (i = 0; i < 28; i++)
|
||||
{
|
||||
for (j = 0; j < 1 << LOMBitsLUT[i]; j++)
|
||||
|
@ -2635,6 +2631,7 @@ int ncrush_generate_tables(NCRUSH_CONTEXT *context)
|
|||
}
|
||||
|
||||
k = 0;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
for (j = 0; j < 1 << CopyOffsetBitsLUT[i]; j++)
|
||||
|
@ -2645,6 +2642,7 @@ int ncrush_generate_tables(NCRUSH_CONTEXT *context)
|
|||
}
|
||||
|
||||
k /= 128;
|
||||
|
||||
for (i = 16; i < 32; i++)
|
||||
{
|
||||
for (j = 0; j < 1 << (CopyOffsetBitsLUT[i] - 7); j++)
|
||||
|
@ -2664,7 +2662,6 @@ void ncrush_context_reset(NCRUSH_CONTEXT* ncrush, BOOL flush)
|
|||
{
|
||||
ZeroMemory(&(ncrush->HistoryBuffer), sizeof(ncrush->HistoryBuffer));
|
||||
ZeroMemory(&(ncrush->OffsetCache), sizeof(ncrush->OffsetCache));
|
||||
|
||||
ZeroMemory(&(ncrush->MatchTable), sizeof(ncrush->MatchTable));
|
||||
ZeroMemory(&(ncrush->HashTable), sizeof(ncrush->HashTable));
|
||||
|
||||
|
@ -2679,21 +2676,16 @@ void ncrush_context_reset(NCRUSH_CONTEXT* ncrush, BOOL flush)
|
|||
NCRUSH_CONTEXT* ncrush_context_new(BOOL Compressor)
|
||||
{
|
||||
NCRUSH_CONTEXT* ncrush;
|
||||
|
||||
ncrush = (NCRUSH_CONTEXT*) calloc(1, sizeof(NCRUSH_CONTEXT));
|
||||
|
||||
if (ncrush)
|
||||
{
|
||||
ncrush->Compressor = Compressor;
|
||||
|
||||
ZeroMemory(&(ncrush->OffsetCache), sizeof(ncrush->OffsetCache));
|
||||
|
||||
ncrush->HistoryBufferSize = 65536;
|
||||
ncrush->HistoryEndOffset = ncrush->HistoryBufferSize - 1;
|
||||
|
||||
ZeroMemory(&(ncrush->HistoryBuffer), sizeof(ncrush->HistoryBuffer));
|
||||
ncrush->HistoryBufferFence = 0xABABABAB;
|
||||
|
||||
ncrush->HistoryOffset = 0;
|
||||
ncrush->HistoryPtr = &(ncrush->HistoryBuffer[ncrush->HistoryOffset]);
|
||||
|
||||
|
|
|
@ -10,9 +10,9 @@ static const BYTE TEST_BELLS_NCRUSH[] =
|
|||
"\xef\xb5\xef\x21\x87\xd0\xc5\xe1\x85\x71\xd4\x10\x16\xe7\xda\xfb"
|
||||
"\x1d\x7e\xe4\xda\x47\x1f\xb0\xef\xbe\xbd\xff\x2f";
|
||||
|
||||
static int test_NCrushCompressBells(void)
|
||||
static BOOL test_NCrushCompressBells(void)
|
||||
{
|
||||
int rc = -1;
|
||||
BOOL rc = FALSE;
|
||||
int status;
|
||||
UINT32 Flags;
|
||||
UINT32 SrcSize;
|
||||
|
@ -22,8 +22,9 @@ static int test_NCrushCompressBells(void)
|
|||
UINT32 expectedSize;
|
||||
BYTE OutputBuffer[65536];
|
||||
NCRUSH_CONTEXT* ncrush = ncrush_context_new(TRUE);
|
||||
|
||||
if (!ncrush)
|
||||
return -1;
|
||||
return rc;
|
||||
|
||||
SrcSize = sizeof(TEST_BELLS_DATA) - 1;
|
||||
pSrcData = (BYTE*) TEST_BELLS_DATA;
|
||||
|
@ -32,13 +33,16 @@ static int test_NCrushCompressBells(void)
|
|||
DstSize = sizeof(OutputBuffer);
|
||||
ZeroMemory(OutputBuffer, sizeof(OutputBuffer));
|
||||
status = ncrush_compress(ncrush, pSrcData, SrcSize, &pDstData, &DstSize, &Flags);
|
||||
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
printf("status: %d Flags: 0x%08"PRIX32" DstSize: %"PRIu32"\n", status, Flags, DstSize);
|
||||
|
||||
if (DstSize != expectedSize)
|
||||
{
|
||||
printf("NCrushCompressBells: output size mismatch: Actual: %"PRIu32", Expected: %"PRIu32"\n", DstSize, expectedSize);
|
||||
printf("NCrushCompressBells: output size mismatch: Actual: %"PRIu32", Expected: %"PRIu32"\n",
|
||||
DstSize, expectedSize);
|
||||
printf("Actual\n");
|
||||
BitDump(__FUNCTION__, WLOG_INFO, pDstData, DstSize * 8, 0);
|
||||
printf("Expected\n");
|
||||
|
@ -56,16 +60,15 @@ static int test_NCrushCompressBells(void)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
rc = 1;
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
ncrush_context_free(ncrush);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int test_NCrushDecompressBells(void)
|
||||
static BOOL test_NCrushDecompressBells(void)
|
||||
{
|
||||
int rc = -1;
|
||||
BOOL rc = FALSE;
|
||||
int status;
|
||||
UINT32 Flags;
|
||||
BYTE* pSrcData;
|
||||
|
@ -76,13 +79,14 @@ static int test_NCrushDecompressBells(void)
|
|||
NCRUSH_CONTEXT* ncrush = ncrush_context_new(FALSE);
|
||||
|
||||
if (!ncrush)
|
||||
return -1;
|
||||
return rc;
|
||||
|
||||
SrcSize = sizeof(TEST_BELLS_NCRUSH) - 1;
|
||||
pSrcData = (BYTE*) TEST_BELLS_NCRUSH;
|
||||
Flags = PACKET_COMPRESSED | 2;
|
||||
expectedSize = sizeof(TEST_BELLS_DATA) - 1;
|
||||
status = ncrush_decompress(ncrush, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
|
||||
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -90,7 +94,8 @@ static int test_NCrushDecompressBells(void)
|
|||
|
||||
if (DstSize != expectedSize)
|
||||
{
|
||||
printf("NCrushDecompressBells: output size mismatch: Actual: %"PRIu32", Expected: %"PRIu32"\n", DstSize, expectedSize);
|
||||
printf("NCrushDecompressBells: output size mismatch: Actual: %"PRIu32", Expected: %"PRIu32"\n",
|
||||
DstSize, expectedSize);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -100,8 +105,7 @@ static int test_NCrushDecompressBells(void)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
rc = 1;
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
ncrush_context_free(ncrush);
|
||||
return rc;
|
||||
|
@ -109,10 +113,10 @@ fail:
|
|||
|
||||
int TestFreeRDPCodecNCrush(int argc, char* argv[])
|
||||
{
|
||||
if (test_NCrushCompressBells() < 0)
|
||||
if (!test_NCrushCompressBells())
|
||||
return -1;
|
||||
|
||||
if (test_NCrushDecompressBells() < 0)
|
||||
if (!test_NCrushDecompressBells())
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -29,10 +29,77 @@
|
|||
#include <winpr/image.h>
|
||||
|
||||
#include "lodepng/lodepng.h"
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include "../log.h"
|
||||
#define TAG WINPR_TAG("utils.image")
|
||||
|
||||
static BOOL writeBitmapFileHeader(wStream* s, const WINPR_BITMAP_FILE_HEADER* bf)
|
||||
{
|
||||
if (!Stream_EnsureRemainingCapacity(s, sizeof(WINPR_BITMAP_FILE_HEADER)))
|
||||
return FALSE;
|
||||
|
||||
Stream_Write_UINT8(s, bf->bfType[0]);
|
||||
Stream_Write_UINT8(s, bf->bfType[1]);
|
||||
Stream_Write_UINT32(s, bf->bfSize);
|
||||
Stream_Write_UINT16(s, bf->bfReserved1);
|
||||
Stream_Write_UINT16(s, bf->bfReserved2);
|
||||
Stream_Write_UINT32(s, bf->bfOffBits);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL readBitmapFileHeader(wStream* s, WINPR_BITMAP_FILE_HEADER* bf)
|
||||
{
|
||||
if (!s || !bf || (Stream_GetRemainingLength(s) < sizeof(WINPR_BITMAP_FILE_HEADER)))
|
||||
return FALSE;
|
||||
|
||||
Stream_Read_UINT8(s, bf->bfType[0]);
|
||||
Stream_Read_UINT8(s, bf->bfType[1]);
|
||||
Stream_Read_UINT32(s, bf->bfSize);
|
||||
Stream_Read_UINT16(s, bf->bfReserved1);
|
||||
Stream_Read_UINT16(s, bf->bfReserved2);
|
||||
Stream_Read_UINT32(s, bf->bfOffBits);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL writeBitmapInfoHeader(wStream* s, const WINPR_BITMAP_INFO_HEADER* bi)
|
||||
{
|
||||
if (!Stream_EnsureRemainingCapacity(s, sizeof(WINPR_BITMAP_INFO_HEADER)))
|
||||
return FALSE;
|
||||
|
||||
Stream_Write_UINT32(s, bi->biSize);
|
||||
Stream_Write_UINT32(s, bi->biWidth);
|
||||
Stream_Write_UINT32(s, bi->biHeight);
|
||||
Stream_Write_UINT16(s, bi->biPlanes);
|
||||
Stream_Write_UINT16(s, bi->biBitCount);
|
||||
Stream_Write_UINT32(s, bi->biCompression);
|
||||
Stream_Write_UINT32(s, bi->biSizeImage);
|
||||
Stream_Write_UINT32(s, bi->biXPelsPerMeter);
|
||||
Stream_Write_UINT32(s, bi->biYPelsPerMeter);
|
||||
Stream_Write_UINT32(s, bi->biClrUsed);
|
||||
Stream_Write_UINT32(s, bi->biClrImportant);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL readBitmapInfoHeader(wStream* s, WINPR_BITMAP_INFO_HEADER* bi)
|
||||
{
|
||||
if (!s || !bi || (Stream_GetRemainingLength(s) < sizeof(WINPR_BITMAP_INFO_HEADER)))
|
||||
return FALSE;
|
||||
|
||||
Stream_Read_UINT32(s, bi->biSize);
|
||||
Stream_Read_INT32(s, bi->biWidth);
|
||||
Stream_Read_INT32(s, bi->biHeight);
|
||||
Stream_Read_UINT16(s, bi->biPlanes);
|
||||
Stream_Read_UINT16(s, bi->biBitCount);
|
||||
Stream_Read_UINT32(s, bi->biCompression);
|
||||
Stream_Read_UINT32(s, bi->biSizeImage);
|
||||
Stream_Read_INT32(s, bi->biXPelsPerMeter);
|
||||
Stream_Read_INT32(s, bi->biYPelsPerMeter);
|
||||
Stream_Read_UINT32(s, bi->biClrUsed);
|
||||
Stream_Read_UINT32(s, bi->biClrImportant);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refer to "Compressed Image File Formats: JPEG, PNG, GIF, XBM, BMP" book
|
||||
*/
|
||||
|
@ -42,8 +109,8 @@ int winpr_bitmap_write(const char* filename, BYTE* data, int width, int height,
|
|||
FILE* fp;
|
||||
WINPR_BITMAP_FILE_HEADER bf;
|
||||
WINPR_BITMAP_INFO_HEADER bi;
|
||||
int ret = 1;
|
||||
|
||||
wStream* s;
|
||||
int ret = -1;
|
||||
fp = fopen(filename, "w+b");
|
||||
|
||||
if (!fp)
|
||||
|
@ -59,7 +126,6 @@ int winpr_bitmap_write(const char* filename, BYTE* data, int width, int height,
|
|||
bf.bfOffBits = sizeof(WINPR_BITMAP_FILE_HEADER) + sizeof(WINPR_BITMAP_INFO_HEADER);
|
||||
bi.biSizeImage = width * height * (bpp / 8);
|
||||
bf.bfSize = bf.bfOffBits + bi.biSizeImage;
|
||||
|
||||
bi.biWidth = width;
|
||||
bi.biHeight = -1 * height;
|
||||
bi.biPlanes = 1;
|
||||
|
@ -70,14 +136,27 @@ int winpr_bitmap_write(const char* filename, BYTE* data, int width, int height,
|
|||
bi.biClrUsed = 0;
|
||||
bi.biClrImportant = 0;
|
||||
bi.biSize = sizeof(WINPR_BITMAP_INFO_HEADER);
|
||||
s = Stream_New(NULL, sizeof(WINPR_BITMAP_FILE_HEADER) + sizeof(WINPR_BITMAP_INFO_HEADER));
|
||||
|
||||
if (fwrite((void*) &bf, sizeof(WINPR_BITMAP_FILE_HEADER), 1, fp) != 1 ||
|
||||
fwrite((void*) &bi, sizeof(WINPR_BITMAP_INFO_HEADER), 1, fp) != 1 ||
|
||||
if (!s)
|
||||
goto fail;
|
||||
|
||||
if (!writeBitmapFileHeader(s, &bf))
|
||||
goto fail;
|
||||
|
||||
if (!writeBitmapInfoHeader(s, &bi))
|
||||
goto fail;
|
||||
|
||||
Stream_SealLength(s);
|
||||
|
||||
if (fwrite(Stream_Buffer(s), Stream_Length(s), 1, fp) != 1 ||
|
||||
fwrite((void*) data, bi.biSizeImage, 1, fp) != 1)
|
||||
ret = -1;
|
||||
goto fail;
|
||||
|
||||
ret = 1;
|
||||
fail:
|
||||
fclose(fp);
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -87,32 +166,29 @@ int winpr_image_write(wImage* image, const char* filename)
|
|||
|
||||
if (image->type == WINPR_IMAGE_BITMAP)
|
||||
{
|
||||
status = winpr_bitmap_write(filename, image->data, image->width, image->height, image->bitsPerPixel);
|
||||
status = winpr_bitmap_write(filename, image->data, image->width, image->height,
|
||||
image->bitsPerPixel);
|
||||
}
|
||||
else
|
||||
{
|
||||
int lodepng_status;
|
||||
|
||||
lodepng_status = lodepng_encode32_file(filename, image->data, image->width, image->height);
|
||||
|
||||
status = (lodepng_status) ? -1 : 1;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int winpr_image_png_read_fp(wImage* image, FILE* fp)
|
||||
static int winpr_image_png_read_fp(wImage* image, FILE* fp)
|
||||
{
|
||||
INT64 size;
|
||||
BYTE* data;
|
||||
UINT32 width;
|
||||
UINT32 height;
|
||||
int lodepng_status;
|
||||
|
||||
_fseeki64(fp, 0, SEEK_END);
|
||||
size = _ftelli64(fp);
|
||||
_fseeki64(fp, 0, SEEK_SET);
|
||||
|
||||
data = (BYTE*) malloc(size);
|
||||
|
||||
if (!data)
|
||||
|
@ -125,7 +201,6 @@ int winpr_image_png_read_fp(wImage* image, FILE* fp)
|
|||
}
|
||||
|
||||
lodepng_status = lodepng_decode32(&(image->data), &width, &height, data, size);
|
||||
|
||||
free(data);
|
||||
|
||||
if (lodepng_status)
|
||||
|
@ -133,20 +208,17 @@ int winpr_image_png_read_fp(wImage* image, FILE* fp)
|
|||
|
||||
image->width = width;
|
||||
image->height = height;
|
||||
|
||||
image->bitsPerPixel = 32;
|
||||
image->bytesPerPixel = 4;
|
||||
image->scanline = image->bytesPerPixel * image->width;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int winpr_image_png_read_buffer(wImage* image, BYTE* buffer, int size)
|
||||
static int winpr_image_png_read_buffer(wImage* image, BYTE* buffer, size_t size)
|
||||
{
|
||||
UINT32 width;
|
||||
UINT32 height;
|
||||
int lodepng_status;
|
||||
|
||||
lodepng_status = lodepng_decode32(&(image->data), &width, &height, buffer, size);
|
||||
|
||||
if (lodepng_status)
|
||||
|
@ -154,37 +226,45 @@ int winpr_image_png_read_buffer(wImage* image, BYTE* buffer, int size)
|
|||
|
||||
image->width = width;
|
||||
image->height = height;
|
||||
|
||||
image->bitsPerPixel = 32;
|
||||
image->bytesPerPixel = 4;
|
||||
image->scanline = image->bytesPerPixel * image->width;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int winpr_image_bitmap_read_fp(wImage* image, FILE* fp)
|
||||
static int winpr_image_bitmap_read_fp(wImage* image, FILE* fp)
|
||||
{
|
||||
int rc = -1;
|
||||
int index;
|
||||
BOOL vFlip;
|
||||
BYTE* pDstData;
|
||||
wStream* s;
|
||||
WINPR_BITMAP_FILE_HEADER bf;
|
||||
WINPR_BITMAP_INFO_HEADER bi;
|
||||
|
||||
if (fread((void*) &bf, sizeof(WINPR_BITMAP_FILE_HEADER), 1, fp) != 1)
|
||||
if (!image || !fp)
|
||||
return -1;
|
||||
|
||||
if ((bf.bfType[0] != 'B') || (bf.bfType[1] != 'M'))
|
||||
image->data = NULL;
|
||||
|
||||
s = Stream_New(NULL, sizeof(WINPR_BITMAP_FILE_HEADER) + sizeof(WINPR_BITMAP_INFO_HEADER));
|
||||
|
||||
if (!s)
|
||||
return -1;
|
||||
|
||||
if (fread(Stream_Buffer(s), Stream_Capacity(s), 1, fp) != 1)
|
||||
goto fail;
|
||||
|
||||
if (!readBitmapFileHeader(s, &bf) || !readBitmapInfoHeader(s, &bi))
|
||||
goto fail;
|
||||
|
||||
if ((bf.bfType[0] != 'B') || (bf.bfType[1] != 'M'))
|
||||
goto fail;
|
||||
|
||||
image->type = WINPR_IMAGE_BITMAP;
|
||||
|
||||
if (fread((void*) &bi, sizeof(WINPR_BITMAP_INFO_HEADER), 1, fp) != 1)
|
||||
return -1;
|
||||
|
||||
if (_ftelli64(fp) != bf.bfOffBits)
|
||||
{
|
||||
_fseeki64(fp, bf.bfOffBits, SEEK_SET);
|
||||
}
|
||||
|
||||
image->width = bi.biWidth;
|
||||
|
||||
|
@ -202,20 +282,15 @@ int winpr_image_bitmap_read_fp(wImage* image, FILE* fp)
|
|||
image->bitsPerPixel = bi.biBitCount;
|
||||
image->bytesPerPixel = (image->bitsPerPixel / 8);
|
||||
image->scanline = (bi.biSizeImage / image->height);
|
||||
|
||||
image->data = (BYTE*) malloc(bi.biSizeImage);
|
||||
|
||||
if (!image->data)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
if (!vFlip)
|
||||
{
|
||||
if (fread((void*) image->data, bi.biSizeImage, 1, fp) != 1)
|
||||
{
|
||||
free(image->data);
|
||||
image->data = NULL;
|
||||
return -1;
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -224,45 +299,50 @@ int winpr_image_bitmap_read_fp(wImage* image, FILE* fp)
|
|||
for (index = 0; index < image->height; index++)
|
||||
{
|
||||
if (fread((void*) pDstData, image->scanline, 1, fp) != 1)
|
||||
{
|
||||
free(image->data);
|
||||
image->data = NULL;
|
||||
return -1;
|
||||
}
|
||||
goto fail;
|
||||
|
||||
pDstData -= image->scanline;
|
||||
}
|
||||
}
|
||||
|
||||
rc = 1;
|
||||
fail:
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
free(image->data);
|
||||
image->data = NULL;
|
||||
}
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int winpr_image_bitmap_read_buffer(wImage* image, BYTE* buffer, int size)
|
||||
static int winpr_image_bitmap_read_buffer(wImage* image, BYTE* buffer, size_t size)
|
||||
{
|
||||
int rc = -1;
|
||||
int index;
|
||||
BOOL vFlip;
|
||||
BYTE* pSrcData;
|
||||
BYTE* pDstData;
|
||||
WINPR_BITMAP_FILE_HEADER bf;
|
||||
WINPR_BITMAP_INFO_HEADER bi;
|
||||
wStream* s = Stream_New(buffer, size);
|
||||
|
||||
pSrcData = buffer;
|
||||
if (!s)
|
||||
return -1;
|
||||
|
||||
CopyMemory(&bf, pSrcData, sizeof(WINPR_BITMAP_FILE_HEADER));
|
||||
pSrcData += sizeof(WINPR_BITMAP_FILE_HEADER);
|
||||
if (!readBitmapFileHeader(s, &bf) || !readBitmapInfoHeader(s, &bi))
|
||||
goto fail;
|
||||
|
||||
if ((bf.bfType[0] != 'B') || (bf.bfType[1] != 'M'))
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
image->type = WINPR_IMAGE_BITMAP;
|
||||
|
||||
CopyMemory(&bi, pSrcData, sizeof(WINPR_BITMAP_INFO_HEADER));
|
||||
pSrcData += sizeof(WINPR_BITMAP_INFO_HEADER);
|
||||
|
||||
if ((pSrcData - buffer) != bf.bfOffBits)
|
||||
{
|
||||
pSrcData = &buffer[bf.bfOffBits];
|
||||
}
|
||||
if (Stream_Capacity(s) < bf.bfOffBits + bi.biSizeImage)
|
||||
goto fail;
|
||||
|
||||
Stream_SetPosition(s, bf.bfOffBits);
|
||||
image->width = bi.biWidth;
|
||||
|
||||
if (bi.biHeight < 0)
|
||||
|
@ -279,27 +359,35 @@ int winpr_image_bitmap_read_buffer(wImage* image, BYTE* buffer, int size)
|
|||
image->bitsPerPixel = bi.biBitCount;
|
||||
image->bytesPerPixel = (image->bitsPerPixel / 8);
|
||||
image->scanline = (bi.biSizeImage / image->height);
|
||||
|
||||
image->data = (BYTE*) malloc(bi.biSizeImage);
|
||||
|
||||
if (!image->data)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
if (!vFlip)
|
||||
CopyMemory(image->data, pSrcData, bi.biSizeImage);
|
||||
Stream_Read(s, image->data, bi.biSizeImage);
|
||||
else
|
||||
{
|
||||
pDstData = &(image->data[(image->height - 1) * image->scanline]);
|
||||
|
||||
for (index = 0; index < image->height; index++)
|
||||
{
|
||||
CopyMemory(pDstData, pSrcData, image->scanline);
|
||||
pSrcData += image->scanline;
|
||||
Stream_Read(s, pDstData, image->scanline);
|
||||
pDstData -= image->scanline;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
rc = 1;
|
||||
fail:
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
free(image->data);
|
||||
image->data = NULL;
|
||||
}
|
||||
|
||||
Stream_Free(s, FALSE);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int winpr_image_read(wImage* image, const char* filename)
|
||||
|
@ -307,7 +395,6 @@ int winpr_image_read(wImage* image, const char* filename)
|
|||
FILE* fp;
|
||||
BYTE sig[8];
|
||||
int status = -1;
|
||||
|
||||
fp = fopen(filename, "rb");
|
||||
|
||||
if (!fp)
|
||||
|
@ -333,8 +420,8 @@ int winpr_image_read(wImage* image, const char* filename)
|
|||
image->type = WINPR_IMAGE_PNG;
|
||||
status = winpr_image_png_read_fp(image, fp);
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
fclose(fp);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -363,10 +450,9 @@ int winpr_image_read_buffer(wImage* image, BYTE* buffer, int size)
|
|||
return status;
|
||||
}
|
||||
|
||||
wImage* winpr_image_new()
|
||||
wImage* winpr_image_new(void)
|
||||
{
|
||||
wImage* image;
|
||||
|
||||
image = (wImage*) calloc(1, sizeof(wImage));
|
||||
|
||||
if (!image)
|
||||
|
|
|
@ -9,12 +9,12 @@
|
|||
#define PATH_MAX 4096
|
||||
#endif
|
||||
|
||||
static void *read_image(const char *src, size_t *size)
|
||||
static void* read_image(const char* src, size_t* size)
|
||||
{
|
||||
int success = 0;
|
||||
void *a = NULL;
|
||||
void* a = NULL;
|
||||
INT64 src_size;
|
||||
FILE *fsrc = fopen(src, "rb");
|
||||
FILE* fsrc = fopen(src, "rb");
|
||||
|
||||
if (!fsrc)
|
||||
{
|
||||
|
@ -52,22 +52,24 @@ static void *read_image(const char *src, size_t *size)
|
|||
|
||||
success = 1;
|
||||
*size = src_size;
|
||||
|
||||
cleanup:
|
||||
|
||||
if (a && !success)
|
||||
{
|
||||
free(a);
|
||||
a = NULL;
|
||||
}
|
||||
|
||||
if (fsrc)
|
||||
fclose(fsrc);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
static int img_compare(wImage *image, wImage *image2, BOOL ignoreType)
|
||||
static int img_compare(wImage* image, wImage* image2, BOOL ignoreType)
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
if ((image->type != image2->type) && !ignoreType)
|
||||
{
|
||||
fprintf(stderr, "Image type mismatch %d:%d\n", image->type, image2->type);
|
||||
|
@ -100,7 +102,8 @@ static int img_compare(wImage *image, wImage *image2, BOOL ignoreType)
|
|||
|
||||
if (image->bytesPerPixel != image2->bytesPerPixel)
|
||||
{
|
||||
fprintf(stderr, "Image bytesPerPixel mismatch %d:%d\n", image->bytesPerPixel, image2->bytesPerPixel);
|
||||
fprintf(stderr, "Image bytesPerPixel mismatch %d:%d\n", image->bytesPerPixel,
|
||||
image2->bytesPerPixel);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
@ -113,11 +116,10 @@ cleanup:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static wImage *get_image(const char *src)
|
||||
static wImage* get_image(const char* src)
|
||||
{
|
||||
int status;
|
||||
wImage* image = NULL;
|
||||
|
||||
image = winpr_image_new();
|
||||
|
||||
if (!image)
|
||||
|
@ -136,17 +138,16 @@ static wImage *get_image(const char *src)
|
|||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
static int create_test(const char *src, const char *dst_png, const char *dst_bmp)
|
||||
static int create_test(const char* src, const char* dst_png, const char* dst_bmp)
|
||||
{
|
||||
int rc = -1;
|
||||
int ret = -1;
|
||||
int status;
|
||||
size_t bsize;
|
||||
void *buffer = NULL;
|
||||
void* buffer = NULL;
|
||||
wImage* image = NULL, *image2 = NULL, *image3 = NULL, *image4 = NULL;
|
||||
|
||||
if (!PathFileExistsA(src))
|
||||
|
@ -182,6 +183,7 @@ static int create_test(const char *src, const char *dst_png, const char *dst_bmp
|
|||
|
||||
/* Read image from buffer, compare. */
|
||||
buffer = read_image(src, &bsize);
|
||||
|
||||
if (!buffer)
|
||||
{
|
||||
fprintf(stderr, "Failed to read image %s!\n", src);
|
||||
|
@ -205,51 +207,59 @@ static int create_test(const char *src, const char *dst_png, const char *dst_bmp
|
|||
}
|
||||
|
||||
rc = img_compare(image, image2, TRUE);
|
||||
|
||||
if (rc)
|
||||
goto cleanup;
|
||||
|
||||
image3 = get_image(dst_png);
|
||||
|
||||
if (!image3)
|
||||
goto cleanup;
|
||||
|
||||
rc = img_compare(image, image3, TRUE);
|
||||
|
||||
if (rc)
|
||||
goto cleanup;
|
||||
|
||||
image4 = get_image(dst_bmp);
|
||||
|
||||
if (!image4)
|
||||
goto cleanup;
|
||||
|
||||
rc = img_compare(image, image4, TRUE);
|
||||
|
||||
if (rc)
|
||||
goto cleanup;
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
|
||||
if (image)
|
||||
winpr_image_free(image, TRUE);
|
||||
|
||||
if (image2)
|
||||
winpr_image_free(image2, TRUE);
|
||||
|
||||
if (image3)
|
||||
winpr_image_free(image3, TRUE);
|
||||
|
||||
if (image4)
|
||||
winpr_image_free(image4, TRUE);
|
||||
|
||||
free(buffer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int test_image_png_to_bmp()
|
||||
static int test_image_png_to_bmp(void)
|
||||
{
|
||||
char *buffer = TEST_SOURCE_PATH;
|
||||
char* buffer = TEST_SOURCE_PATH;
|
||||
char src_png[PATH_MAX];
|
||||
char src_bmp[PATH_MAX];
|
||||
char dst_png[PATH_MAX];
|
||||
char dst_bmp[PATH_MAX];
|
||||
char dst_png2[PATH_MAX];
|
||||
char dst_bmp2[PATH_MAX];
|
||||
char *tmp = GetKnownPath(KNOWN_PATH_TEMP);
|
||||
char* tmp = GetKnownPath(KNOWN_PATH_TEMP);
|
||||
|
||||
if (!tmp)
|
||||
return -1;
|
||||
|
@ -276,7 +286,6 @@ int test_image_png_to_bmp()
|
|||
int TestImage(int argc, char* argv[])
|
||||
{
|
||||
int rc = test_image_png_to_bmp();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue