📄 vncencodetight.cpp
字号:
}
void
vncEncodeTight::FillPalette8(int count)
{
CARD8 *data = (CARD8 *)m_buffer;
CARD8 c0, c1;
int i, n0, n1;
m_paletteNumColors = 0;
c0 = data[0];
for (i = 1; i < count && data[i] == c0; i++);
if (i == count) {
m_paletteNumColors = 1;
return; // Solid rectangle
}
if (m_paletteMaxColors < 2)
return;
n0 = i;
c1 = data[i];
n1 = 0;
for (i++; i < count; i++) {
if (data[i] == c0) {
n0++;
} else if (data[i] == c1) {
n1++;
} else
break;
}
if (i == count) {
if (n0 > n1) {
m_monoBackground = (CARD32)c0;
m_monoForeground = (CARD32)c1;
} else {
m_monoBackground = (CARD32)c1;
m_monoForeground = (CARD32)c0;
}
m_paletteNumColors = 2; // Two colors
}
}
#define DEFINE_FILL_PALETTE_FUNCTION(bpp) \
\
void \
vncEncodeTight::FillPalette##bpp(int count) \
{ \
CARD##bpp *data = (CARD##bpp *)m_buffer; \
CARD##bpp c0, c1, ci; \
int i, n0, n1, ni; \
\
c0 = data[0]; \
for (i = 1; i < count && data[i] == c0; i++); \
if (i >= count) { \
m_paletteNumColors = 1; /* Solid rectangle */ \
return; \
} \
\
if (m_paletteMaxColors < 2) { \
m_paletteNumColors = 0; /* Full-color format preferred */ \
return; \
} \
\
n0 = i; \
c1 = data[i]; \
n1 = 0; \
for (i++; i < count; i++) { \
ci = data[i]; \
if (ci == c0) { \
n0++; \
} else if (ci == c1) { \
n1++; \
} else \
break; \
} \
if (i >= count) { \
if (n0 > n1) { \
m_monoBackground = (CARD32)c0; \
m_monoForeground = (CARD32)c1; \
} else { \
m_monoBackground = (CARD32)c1; \
m_monoForeground = (CARD32)c0; \
} \
m_paletteNumColors = 2; /* Two colors */ \
return; \
} \
\
PaletteReset(); \
PaletteInsert (c0, (CARD32)n0, bpp); \
PaletteInsert (c1, (CARD32)n1, bpp); \
\
ni = 1; \
for (i++; i < count; i++) { \
if (data[i] == ci) { \
ni++; \
} else { \
if (!PaletteInsert (ci, (CARD32)ni, bpp)) \
return; \
ci = data[i]; \
ni = 1; \
} \
} \
PaletteInsert (ci, (CARD32)ni, bpp); \
}
DEFINE_FILL_PALETTE_FUNCTION(16)
DEFINE_FILL_PALETTE_FUNCTION(32)
//
// Functions to operate with palette structures.
//
#define HASH_FUNC16(rgb) ((int)(((rgb >> 8) + rgb) & 0xFF))
#define HASH_FUNC32(rgb) ((int)(((rgb >> 16) + (rgb >> 8)) & 0xFF))
void
vncEncodeTight::PaletteReset(void)
{
m_paletteNumColors = 0;
memset(m_palette.hash, 0, 256 * sizeof(COLOR_LIST *));
}
int
vncEncodeTight::PaletteInsert(CARD32 rgb, int numPixels, int bpp)
{
COLOR_LIST *pnode;
COLOR_LIST *prev_pnode = NULL;
int hash_key, idx, new_idx, count;
hash_key = (bpp == 16) ? HASH_FUNC16(rgb) : HASH_FUNC32(rgb);
pnode = m_palette.hash[hash_key];
while (pnode != NULL) {
if (pnode->rgb == rgb) {
// Such palette entry already exists.
new_idx = idx = pnode->idx;
count = m_palette.entry[idx].numPixels + numPixels;
if (new_idx && m_palette.entry[new_idx-1].numPixels < count) {
do {
m_palette.entry[new_idx] = m_palette.entry[new_idx-1];
m_palette.entry[new_idx].listNode->idx = new_idx;
new_idx--;
}
while (new_idx &&
m_palette.entry[new_idx-1].numPixels < count);
m_palette.entry[new_idx].listNode = pnode;
pnode->idx = new_idx;
}
m_palette.entry[new_idx].numPixels = count;
return m_paletteNumColors;
}
prev_pnode = pnode;
pnode = pnode->next;
}
// Check if palette is full.
if ( m_paletteNumColors == 256 ||
m_paletteNumColors == m_paletteMaxColors ) {
m_paletteNumColors = 0;
return 0;
}
// Move palette entries with lesser pixel counts.
for ( idx = m_paletteNumColors;
idx > 0 && m_palette.entry[idx-1].numPixels < numPixels;
idx-- ) {
m_palette.entry[idx] = m_palette.entry[idx-1];
m_palette.entry[idx].listNode->idx = idx;
}
// Add new palette entry into the freed slot.
pnode = &m_palette.list[m_paletteNumColors];
if (prev_pnode != NULL) {
prev_pnode->next = pnode;
} else {
m_palette.hash[hash_key] = pnode;
}
pnode->next = NULL;
pnode->idx = idx;
pnode->rgb = rgb;
m_palette.entry[idx].listNode = pnode;
m_palette.entry[idx].numPixels = numPixels;
return (++m_paletteNumColors);
}
//
// Converting 32-bit color samples into 24-bit colors.
// Should be called only when redMax, greenMax and blueMax are 255.
// Color components assumed to be byte-aligned.
//
void
vncEncodeTight::Pack24(BYTE *buf, int count)
{
CARD32 *buf32;
CARD32 pix;
int r_shift, g_shift, b_shift;
buf32 = (CARD32 *)buf;
if (!m_localformat.bigEndian == !m_remoteformat.bigEndian) {
r_shift = m_remoteformat.redShift;
g_shift = m_remoteformat.greenShift;
b_shift = m_remoteformat.blueShift;
} else {
r_shift = 24 - m_remoteformat.redShift;
g_shift = 24 - m_remoteformat.greenShift;
b_shift = 24 - m_remoteformat.blueShift;
}
while (count--) {
pix = *buf32++;
*buf++ = (char)(pix >> r_shift);
*buf++ = (char)(pix >> g_shift);
*buf++ = (char)(pix >> b_shift);
}
}
//
// Converting truecolor samples into palette indices.
//
#define DEFINE_IDX_ENCODE_FUNCTION(bpp) \
\
void \
vncEncodeTight::EncodeIndexedRect##bpp(BYTE *buf, int count) \
{ \
COLOR_LIST *pnode; \
CARD##bpp *src; \
CARD##bpp rgb; \
int rep = 0; \
\
src = (CARD##bpp *) buf; \
\
while (count--) { \
rgb = *src++; \
while (count && *src == rgb) { \
rep++, src++, count--; \
} \
pnode = m_palette.hash[HASH_FUNC##bpp(rgb)]; \
while (pnode != NULL) { \
if ((CARD##bpp)pnode->rgb == rgb) { \
*buf++ = (CARD8)pnode->idx; \
while (rep) { \
*buf++ = (CARD8)pnode->idx; \
rep--; \
} \
break; \
} \
pnode = pnode->next; \
} \
} \
}
DEFINE_IDX_ENCODE_FUNCTION(16)
DEFINE_IDX_ENCODE_FUNCTION(32)
#define DEFINE_MONO_ENCODE_FUNCTION(bpp) \
\
void \
vncEncodeTight::EncodeMonoRect##bpp(BYTE *buf, int w, int h) \
{ \
CARD##bpp *ptr; \
CARD##bpp bg; \
unsigned int value, mask; \
int aligned_width; \
int x, y, bg_bits; \
\
ptr = (CARD##bpp *) buf; \
bg = (CARD##bpp) m_monoBackground; \
aligned_width = w - w % 8; \
\
for (y = 0; y < h; y++) { \
for (x = 0; x < aligned_width; x += 8) { \
for (bg_bits = 0; bg_bits < 8; bg_bits++) { \
if (*ptr++ != bg) \
break; \
} \
if (bg_bits == 8) { \
*buf++ = 0; \
continue; \
} \
mask = 0x80 >> bg_bits; \
value = mask; \
for (bg_bits++; bg_bits < 8; bg_bits++) { \
mask >>= 1; \
if (*ptr++ != bg) { \
value |= mask; \
} \
} \
*buf++ = (CARD8)value; \
} \
\
mask = 0x80; \
value = 0; \
if (x >= w) \
continue; \
\
for (; x < w; x++) { \
if (*ptr++ != bg) { \
value |= mask; \
} \
mask >>= 1; \
} \
*buf++ = (CARD8)value; \
} \
}
DEFINE_MONO_ENCODE_FUNCTION(8)
DEFINE_MONO_ENCODE_FUNCTION(16)
DEFINE_MONO_ENCODE_FUNCTION(32)
//
// ``Gradient'' filter for 24-bit color samples.
// Should be called only when redMax, greenMax and blueMax are 255.
// Color components assumed to be byte-aligned.
//
void
vncEncodeTight::FilterGradient24(BYTE *buf, int w, int h)
{
CARD32 *buf32;
CARD32 pix32;
int *prevRowPtr;
int shiftBits[3];
int pixHere[3], pixUpper[3], pixLeft[3], pixUpperLeft[3];
int prediction;
int x, y, c;
buf32 = (CARD32 *)buf;
memset (m_prevRowBuf, 0, w * 3 * sizeof(int));
if (!m_localformat.bigEndian == !m_remoteformat.bigEndian) {
shiftBits[0] = m_remoteformat.redShift;
shiftBits[1] = m_remoteformat.greenShift;
shiftBits[2] = m_remoteformat.blueShift;
} else {
shiftBits[0] = 24 - m_remoteformat.redShift;
shiftBits[1] = 24 - m_remoteformat.greenShift;
shiftBits[2] = 24 - m_remoteformat.blueShift;
}
for (y = 0; y < h; y++) {
for (c = 0; c < 3; c++) {
pixUpper[c] = 0;
pixHere[c] = 0;
}
prevRowPtr = m_prevRowBuf;
for (x = 0; x < w; x++) {
pix32 = *buf32++;
for (c = 0; c < 3; c++) {
pixUpperLeft[c] = pixUpper[c];
pixLeft[c] = pixHere[c];
pixUpper[c] = *prevRowPtr;
pixHere[c] = (int)(pix32 >> shiftBits[c] & 0xFF);
*prevRowPtr++ = pixHere[c];
prediction = pixLeft[c] + pixUpper[c] - pixUpperLeft[c];
if (prediction < 0) {
prediction = 0;
} else if (prediction > 0xFF) {
prediction = 0xFF;
}
*buf++ = (BYTE)(pixHere[c] - prediction);
}
}
}
}
//
// ``Gradient'' filter for other color depths.
//
#define DEFINE_GRADIENT_FILTER_FUNCTION(bpp) \
\
void \
vncEncodeTight::FilterGradient##bpp(CARD##bpp *buf, int w, int h) \
{ \
CARD##bpp pix, diff; \
bool endianMismatch; \
int *prevRowPtr; \
int maxColor[3], shiftBits[3]; \
int pixHere[3], pixUpper[3], pixLeft[3], pixUpperLeft[3]; \
int prediction; \
int x, y, c; \
\
memset (m_prevRowBuf, 0, w * 3 * sizeof(int)); \
\
endianMismatch = (!m_localformat.bigEndian != !m_remoteformat.bigEndian); \
\
maxColor[0] = m_remoteformat.redMax; \
maxColor[1] = m_remoteformat.greenMax; \
maxColor[2] = m_remoteformat.blueMax; \
shiftBits[0] = m_remoteformat.redShift; \
shiftBits[1] = m_remoteformat.greenShift; \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -