|
|
@ -1,4 +1,7 @@
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Copyright (C) 2017 D. R. Commander. All Rights Reserved.
|
|
|
|
|
|
|
|
* Copyright (C) 2004-2008 Sun Microsystems, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
* Copyright (C) 2004 Landmark Graphics Corporation. All Rights Reserved.
|
|
|
|
* Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
|
|
|
|
* Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* This is free software; you can redistribute it and/or modify
|
|
|
|
* This is free software; you can redistribute it and/or modify
|
|
|
@ -71,16 +74,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
/* Type declarations */
|
|
|
|
/* Type declarations */
|
|
|
|
|
|
|
|
|
|
|
|
typedef void (*filterPtrBPP)(rfbClient* client, int, CARDBPP *);
|
|
|
|
typedef void (*filterPtrBPP)(rfbClient* client, int, int, int);
|
|
|
|
|
|
|
|
|
|
|
|
/* Prototypes */
|
|
|
|
/* Prototypes */
|
|
|
|
|
|
|
|
|
|
|
|
static int InitFilterCopyBPP (rfbClient* client, int rw, int rh);
|
|
|
|
static int InitFilterCopyBPP (rfbClient* client, int rw, int rh);
|
|
|
|
static int InitFilterPaletteBPP (rfbClient* client, int rw, int rh);
|
|
|
|
static int InitFilterPaletteBPP (rfbClient* client, int rw, int rh);
|
|
|
|
static int InitFilterGradientBPP (rfbClient* client, int rw, int rh);
|
|
|
|
static int InitFilterGradientBPP (rfbClient* client, int rw, int rh);
|
|
|
|
static void FilterCopyBPP (rfbClient* client, int numRows, CARDBPP *destBuffer);
|
|
|
|
static void FilterCopyBPP (rfbClient* client, int srcx, int srcy, int numRows);
|
|
|
|
static void FilterPaletteBPP (rfbClient* client, int numRows, CARDBPP *destBuffer);
|
|
|
|
static void FilterPaletteBPP (rfbClient* client, int srcx, int srcy, int numRows);
|
|
|
|
static void FilterGradientBPP (rfbClient* client, int numRows, CARDBPP *destBuffer);
|
|
|
|
static void FilterGradientBPP (rfbClient* client, int srcx, int srcy, int numRows);
|
|
|
|
|
|
|
|
|
|
|
|
#if BPP != 8
|
|
|
|
#if BPP != 8
|
|
|
|
static rfbBool DecompressJpegRectBPP(rfbClient* client, int x, int y, int w, int h);
|
|
|
|
static rfbBool DecompressJpegRectBPP(rfbClient* client, int x, int y, int w, int h);
|
|
|
@ -96,9 +99,17 @@ HandleTightBPP (rfbClient* client, int rx, int ry, int rw, int rh)
|
|
|
|
uint8_t filter_id;
|
|
|
|
uint8_t filter_id;
|
|
|
|
filterPtrBPP filterFn;
|
|
|
|
filterPtrBPP filterFn;
|
|
|
|
z_streamp zs;
|
|
|
|
z_streamp zs;
|
|
|
|
char *buffer2;
|
|
|
|
|
|
|
|
int err, stream_id, compressedLen, bitsPixel;
|
|
|
|
int err, stream_id, compressedLen, bitsPixel;
|
|
|
|
int bufferSize, rowSize, numRows, portionLen, rowsProcessed, extraBytes;
|
|
|
|
int bufferSize, rowSize, numRows, portionLen, rowsProcessed, extraBytes;
|
|
|
|
|
|
|
|
rfbBool readUncompressed = FALSE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (client->frameBuffer == NULL)
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (rx + rw > client->width || ry + rh > client->height) {
|
|
|
|
|
|
|
|
rfbClientLog("Rect out of bounds: %dx%d at (%d, %d)\n", rx, ry, rw, rh);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!ReadFromRFBServer(client, (char *)&comp_ctl, 1))
|
|
|
|
if (!ReadFromRFBServer(client, (char *)&comp_ctl, 1))
|
|
|
|
return FALSE;
|
|
|
|
return FALSE;
|
|
|
@ -114,6 +125,11 @@ HandleTightBPP (rfbClient* client, int rx, int ry, int rw, int rh)
|
|
|
|
comp_ctl >>= 1;
|
|
|
|
comp_ctl >>= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((comp_ctl & rfbTightNoZlib) == rfbTightNoZlib) {
|
|
|
|
|
|
|
|
comp_ctl &= ~(rfbTightNoZlib);
|
|
|
|
|
|
|
|
readUncompressed = TRUE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Handle solid rectangles. */
|
|
|
|
/* Handle solid rectangles. */
|
|
|
|
if (comp_ctl == rfbTightFill) {
|
|
|
|
if (comp_ctl == rfbTightFill) {
|
|
|
|
#if BPP == 32
|
|
|
|
#if BPP == 32
|
|
|
@ -195,10 +211,7 @@ HandleTightBPP (rfbClient* client, int rx, int ry, int rw, int rh)
|
|
|
|
if (!ReadFromRFBServer(client, (char*)client->buffer, rh * rowSize))
|
|
|
|
if (!ReadFromRFBServer(client, (char*)client->buffer, rh * rowSize))
|
|
|
|
return FALSE;
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
|
|
buffer2 = &client->buffer[TIGHT_MIN_TO_COMPRESS * 4];
|
|
|
|
filterFn(client, rx, ry, rh);
|
|
|
|
filterFn(client, rh, (CARDBPP *)buffer2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
client->GotBitmap(client, (uint8_t *)buffer2, rx, ry, rw, rh);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -209,6 +222,14 @@ HandleTightBPP (rfbClient* client, int rx, int ry, int rw, int rh)
|
|
|
|
rfbClientLog("Incorrect data received from the server.\n");
|
|
|
|
rfbClientLog("Incorrect data received from the server.\n");
|
|
|
|
return FALSE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (readUncompressed) {
|
|
|
|
|
|
|
|
if (!ReadFromRFBServer(client, (char*)client->buffer, compressedLen))
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
filterFn(client, rx, ry, rh);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Now let's initialize compression stream if needed. */
|
|
|
|
/* Now let's initialize compression stream if needed. */
|
|
|
|
stream_id = comp_ctl & 0x03;
|
|
|
|
stream_id = comp_ctl & 0x03;
|
|
|
@ -229,7 +250,6 @@ HandleTightBPP (rfbClient* client, int rx, int ry, int rw, int rh)
|
|
|
|
/* Read, decode and draw actual pixel data in a loop. */
|
|
|
|
/* Read, decode and draw actual pixel data in a loop. */
|
|
|
|
|
|
|
|
|
|
|
|
bufferSize = RFB_BUFFER_SIZE * bitsPixel / (bitsPixel + BPP) & 0xFFFFFFFC;
|
|
|
|
bufferSize = RFB_BUFFER_SIZE * bitsPixel / (bitsPixel + BPP) & 0xFFFFFFFC;
|
|
|
|
buffer2 = &client->buffer[bufferSize];
|
|
|
|
|
|
|
|
if (rowSize > bufferSize) {
|
|
|
|
if (rowSize > bufferSize) {
|
|
|
|
/* Should be impossible when RFB_BUFFER_SIZE >= 16384 */
|
|
|
|
/* Should be impossible when RFB_BUFFER_SIZE >= 16384 */
|
|
|
|
rfbClientLog("Internal error: incorrect buffer size.\n");
|
|
|
|
rfbClientLog("Internal error: incorrect buffer size.\n");
|
|
|
@ -271,14 +291,12 @@ HandleTightBPP (rfbClient* client, int rx, int ry, int rw, int rh)
|
|
|
|
|
|
|
|
|
|
|
|
numRows = (bufferSize - zs->avail_out) / rowSize;
|
|
|
|
numRows = (bufferSize - zs->avail_out) / rowSize;
|
|
|
|
|
|
|
|
|
|
|
|
filterFn(client, numRows, (CARDBPP *)buffer2);
|
|
|
|
filterFn(client, rx, ry+rowsProcessed, numRows);
|
|
|
|
|
|
|
|
|
|
|
|
extraBytes = bufferSize - zs->avail_out - numRows * rowSize;
|
|
|
|
extraBytes = bufferSize - zs->avail_out - numRows * rowSize;
|
|
|
|
if (extraBytes > 0)
|
|
|
|
if (extraBytes > 0)
|
|
|
|
memcpy(client->buffer, &client->buffer[numRows * rowSize], extraBytes);
|
|
|
|
memcpy(client->buffer, &client->buffer[numRows * rowSize], extraBytes);
|
|
|
|
|
|
|
|
|
|
|
|
client->GotBitmap(client, (uint8_t *)buffer2, rx, ry+rowsProcessed, rw, numRows);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rowsProcessed += numRows;
|
|
|
|
rowsProcessed += numRows;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (zs->avail_out == 0);
|
|
|
|
while (zs->avail_out == 0);
|
|
|
@ -317,16 +335,19 @@ InitFilterCopyBPP (rfbClient* client, int rw, int rh)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
static void
|
|
|
|
FilterCopyBPP (rfbClient* client, int numRows, CARDBPP *dst)
|
|
|
|
FilterCopyBPP (rfbClient* client, int srcx, int srcy, int numRows)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
CARDBPP *dst =
|
|
|
|
|
|
|
|
(CARDBPP *)&client->frameBuffer[(srcy * client->width + srcx) * BPP / 8];
|
|
|
|
|
|
|
|
int y;
|
|
|
|
|
|
|
|
|
|
|
|
#if BPP == 32
|
|
|
|
#if BPP == 32
|
|
|
|
int x, y;
|
|
|
|
int x;
|
|
|
|
|
|
|
|
|
|
|
|
if (client->cutZeros) {
|
|
|
|
if (client->cutZeros) {
|
|
|
|
for (y = 0; y < numRows; y++) {
|
|
|
|
for (y = 0; y < numRows; y++) {
|
|
|
|
for (x = 0; x < client->rectWidth; x++) {
|
|
|
|
for (x = 0; x < client->rectWidth; x++) {
|
|
|
|
dst[y*client->rectWidth+x] =
|
|
|
|
dst[y*client->width+x] =
|
|
|
|
RGB24_TO_PIXEL32(client->buffer[(y*client->rectWidth+x)*3],
|
|
|
|
RGB24_TO_PIXEL32(client->buffer[(y*client->rectWidth+x)*3],
|
|
|
|
client->buffer[(y*client->rectWidth+x)*3+1],
|
|
|
|
client->buffer[(y*client->rectWidth+x)*3+1],
|
|
|
|
client->buffer[(y*client->rectWidth+x)*3+2]);
|
|
|
|
client->buffer[(y*client->rectWidth+x)*3+2]);
|
|
|
@ -336,7 +357,9 @@ FilterCopyBPP (rfbClient* client, int numRows, CARDBPP *dst)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
memcpy (dst, client->buffer, numRows * client->rectWidth * (BPP / 8));
|
|
|
|
for (y = 0; y < numRows; y++)
|
|
|
|
|
|
|
|
memcpy (&dst[y*client->width], &client->buffer[y*client->rectWidth],
|
|
|
|
|
|
|
|
client->rectWidth * (BPP / 8));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
static int
|
|
|
@ -356,8 +379,10 @@ InitFilterGradientBPP (rfbClient* client, int rw, int rh)
|
|
|
|
#if BPP == 32
|
|
|
|
#if BPP == 32
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
static void
|
|
|
|
FilterGradient24 (rfbClient* client, int numRows, uint32_t *dst)
|
|
|
|
FilterGradient24 (rfbClient* client, int srcx, int srcy, int numRows)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
CARDBPP *dst =
|
|
|
|
|
|
|
|
(CARDBPP *)&client->frameBuffer[(srcy * client->width + srcx) * BPP / 8];
|
|
|
|
int x, y, c;
|
|
|
|
int x, y, c;
|
|
|
|
uint8_t thisRow[2048*3];
|
|
|
|
uint8_t thisRow[2048*3];
|
|
|
|
uint8_t pix[3];
|
|
|
|
uint8_t pix[3];
|
|
|
@ -370,7 +395,7 @@ FilterGradient24 (rfbClient* client, int numRows, uint32_t *dst)
|
|
|
|
pix[c] = client->tightPrevRow[c] + client->buffer[y*client->rectWidth*3+c];
|
|
|
|
pix[c] = client->tightPrevRow[c] + client->buffer[y*client->rectWidth*3+c];
|
|
|
|
thisRow[c] = pix[c];
|
|
|
|
thisRow[c] = pix[c];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dst[y*client->rectWidth] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]);
|
|
|
|
dst[y*client->width] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]);
|
|
|
|
|
|
|
|
|
|
|
|
/* Remaining pixels of a row */
|
|
|
|
/* Remaining pixels of a row */
|
|
|
|
for (x = 1; x < client->rectWidth; x++) {
|
|
|
|
for (x = 1; x < client->rectWidth; x++) {
|
|
|
@ -385,7 +410,7 @@ FilterGradient24 (rfbClient* client, int numRows, uint32_t *dst)
|
|
|
|
pix[c] = (uint8_t)est[c] + client->buffer[(y*client->rectWidth+x)*3+c];
|
|
|
|
pix[c] = (uint8_t)est[c] + client->buffer[(y*client->rectWidth+x)*3+c];
|
|
|
|
thisRow[x*3+c] = pix[c];
|
|
|
|
thisRow[x*3+c] = pix[c];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dst[y*client->rectWidth+x] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]);
|
|
|
|
dst[y*client->width+x] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(client->tightPrevRow, thisRow, client->rectWidth * 3);
|
|
|
|
memcpy(client->tightPrevRow, thisRow, client->rectWidth * 3);
|
|
|
@ -395,8 +420,10 @@ FilterGradient24 (rfbClient* client, int numRows, uint32_t *dst)
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
static void
|
|
|
|
FilterGradientBPP (rfbClient* client, int numRows, CARDBPP *dst)
|
|
|
|
FilterGradientBPP (rfbClient* client, int srcx, int srcy, int numRows)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
CARDBPP *dst =
|
|
|
|
|
|
|
|
(CARDBPP *)&client->frameBuffer[(srcy * client->width + srcx) * BPP / 8];
|
|
|
|
int x, y, c;
|
|
|
|
int x, y, c;
|
|
|
|
CARDBPP *src = (CARDBPP *)client->buffer;
|
|
|
|
CARDBPP *src = (CARDBPP *)client->buffer;
|
|
|
|
uint16_t *thatRow = (uint16_t *)client->tightPrevRow;
|
|
|
|
uint16_t *thatRow = (uint16_t *)client->tightPrevRow;
|
|
|
@ -408,7 +435,7 @@ FilterGradientBPP (rfbClient* client, int numRows, CARDBPP *dst)
|
|
|
|
|
|
|
|
|
|
|
|
#if BPP == 32
|
|
|
|
#if BPP == 32
|
|
|
|
if (client->cutZeros) {
|
|
|
|
if (client->cutZeros) {
|
|
|
|
FilterGradient24(client, numRows, dst);
|
|
|
|
FilterGradient24(client, srcx, srcy, numRows);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
@ -428,7 +455,7 @@ FilterGradientBPP (rfbClient* client, int numRows, CARDBPP *dst)
|
|
|
|
pix[c] = (uint16_t)(((src[y*client->rectWidth] >> shift[c]) + thatRow[c]) & max[c]);
|
|
|
|
pix[c] = (uint16_t)(((src[y*client->rectWidth] >> shift[c]) + thatRow[c]) & max[c]);
|
|
|
|
thisRow[c] = pix[c];
|
|
|
|
thisRow[c] = pix[c];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dst[y*client->rectWidth] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]);
|
|
|
|
dst[y*client->width] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]);
|
|
|
|
|
|
|
|
|
|
|
|
/* Remaining pixels of a row */
|
|
|
|
/* Remaining pixels of a row */
|
|
|
|
for (x = 1; x < client->rectWidth; x++) {
|
|
|
|
for (x = 1; x < client->rectWidth; x++) {
|
|
|
@ -442,7 +469,7 @@ FilterGradientBPP (rfbClient* client, int numRows, CARDBPP *dst)
|
|
|
|
pix[c] = (uint16_t)(((src[y*client->rectWidth+x] >> shift[c]) + est[c]) & max[c]);
|
|
|
|
pix[c] = (uint16_t)(((src[y*client->rectWidth+x] >> shift[c]) + est[c]) & max[c]);
|
|
|
|
thisRow[x*3+c] = pix[c];
|
|
|
|
thisRow[x*3+c] = pix[c];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dst[y*client->rectWidth+x] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]);
|
|
|
|
dst[y*client->width+x] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
memcpy(thatRow, thisRow, client->rectWidth * 3 * sizeof(uint16_t));
|
|
|
|
memcpy(thatRow, thisRow, client->rectWidth * 3 * sizeof(uint16_t));
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -487,9 +514,11 @@ InitFilterPaletteBPP (rfbClient* client, int rw, int rh)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
static void
|
|
|
|
FilterPaletteBPP (rfbClient* client, int numRows, CARDBPP *dst)
|
|
|
|
FilterPaletteBPP (rfbClient* client, int srcx, int srcy, int numRows)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int x, y, b, w;
|
|
|
|
int x, y, b, w;
|
|
|
|
|
|
|
|
CARDBPP *dst =
|
|
|
|
|
|
|
|
(CARDBPP *)&client->frameBuffer[(srcy * client->width + srcx) * BPP / 8];
|
|
|
|
uint8_t *src = (uint8_t *)client->buffer;
|
|
|
|
uint8_t *src = (uint8_t *)client->buffer;
|
|
|
|
CARDBPP *palette = (CARDBPP *)client->tightPalette;
|
|
|
|
CARDBPP *palette = (CARDBPP *)client->tightPalette;
|
|
|
|
|
|
|
|
|
|
|
@ -498,16 +527,16 @@ FilterPaletteBPP (rfbClient* client, int numRows, CARDBPP *dst)
|
|
|
|
for (y = 0; y < numRows; y++) {
|
|
|
|
for (y = 0; y < numRows; y++) {
|
|
|
|
for (x = 0; x < client->rectWidth / 8; x++) {
|
|
|
|
for (x = 0; x < client->rectWidth / 8; x++) {
|
|
|
|
for (b = 7; b >= 0; b--)
|
|
|
|
for (b = 7; b >= 0; b--)
|
|
|
|
dst[y*client->rectWidth+x*8+7-b] = palette[src[y*w+x] >> b & 1];
|
|
|
|
dst[y*client->width+x*8+7-b] = palette[src[y*w+x] >> b & 1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (b = 7; b >= 8 - client->rectWidth % 8; b--) {
|
|
|
|
for (b = 7; b >= 8 - client->rectWidth % 8; b--) {
|
|
|
|
dst[y*client->rectWidth+x*8+7-b] = palette[src[y*w+x] >> b & 1];
|
|
|
|
dst[y*client->width+x*8+7-b] = palette[src[y*w+x] >> b & 1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
for (y = 0; y < numRows; y++)
|
|
|
|
for (y = 0; y < numRows; y++)
|
|
|
|
for (x = 0; x < client->rectWidth; x++)
|
|
|
|
for (x = 0; x < client->rectWidth; x++)
|
|
|
|
dst[y*client->rectWidth+x] = palette[(int)src[y*client->rectWidth+x]];
|
|
|
|
dst[y*client->width+x] = palette[(int)src[y*client->rectWidth+x]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -522,13 +551,9 @@ FilterPaletteBPP (rfbClient* client, int numRows, CARDBPP *dst)
|
|
|
|
static rfbBool
|
|
|
|
static rfbBool
|
|
|
|
DecompressJpegRectBPP(rfbClient* client, int x, int y, int w, int h)
|
|
|
|
DecompressJpegRectBPP(rfbClient* client, int x, int y, int w, int h)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct jpeg_decompress_struct cinfo;
|
|
|
|
|
|
|
|
struct jpeg_error_mgr jerr;
|
|
|
|
|
|
|
|
int compressedLen;
|
|
|
|
int compressedLen;
|
|
|
|
uint8_t *compressedData;
|
|
|
|
uint8_t *compressedData, *dst;
|
|
|
|
CARDBPP *pixelPtr;
|
|
|
|
int pixelSize, pitch, flags = 0;
|
|
|
|
JSAMPROW rowPointer[1];
|
|
|
|
|
|
|
|
int dx, dy;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
compressedLen = (int)ReadCompactLen(client);
|
|
|
|
compressedLen = (int)ReadCompactLen(client);
|
|
|
|
if (compressedLen <= 0) {
|
|
|
|
if (compressedLen <= 0) {
|
|
|
@ -550,47 +575,57 @@ DecompressJpegRectBPP(rfbClient* client, int x, int y, int w, int h)
|
|
|
|
if(client->GotJpeg != NULL)
|
|
|
|
if(client->GotJpeg != NULL)
|
|
|
|
return client->GotJpeg(client, compressedData, compressedLen, x, y, w, h);
|
|
|
|
return client->GotJpeg(client, compressedData, compressedLen, x, y, w, h);
|
|
|
|
|
|
|
|
|
|
|
|
cinfo.err = jpeg_std_error(&jerr);
|
|
|
|
if (!client->tjhnd) {
|
|
|
|
cinfo.client_data = client;
|
|
|
|
if ((client->tjhnd = tjInitDecompress()) == NULL) {
|
|
|
|
jpeg_create_decompress(&cinfo);
|
|
|
|
rfbClientLog("TurboJPEG error: %s\n", tjGetErrorStr());
|
|
|
|
|
|
|
|
free(compressedData);
|
|
|
|
JpegSetSrcManager(&cinfo, compressedData, compressedLen);
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
jpeg_read_header(&cinfo, TRUE);
|
|
|
|
#if BPP == 16
|
|
|
|
cinfo.out_color_space = JCS_RGB;
|
|
|
|
flags = 0;
|
|
|
|
|
|
|
|
pixelSize = 3;
|
|
|
|
|
|
|
|
pitch = w * pixelSize;
|
|
|
|
|
|
|
|
dst = (uint8_t *)client->buffer;
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
if (client->format.bigEndian) flags |= TJ_ALPHAFIRST;
|
|
|
|
|
|
|
|
if (client->format.redShift == 16 && client->format.blueShift == 0)
|
|
|
|
|
|
|
|
flags |= TJ_BGR;
|
|
|
|
|
|
|
|
if (client->format.bigEndian) flags ^= TJ_BGR;
|
|
|
|
|
|
|
|
pixelSize = BPP / 8;
|
|
|
|
|
|
|
|
pitch = client->width * pixelSize;
|
|
|
|
|
|
|
|
dst = &client->frameBuffer[y * pitch + x * pixelSize];
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
jpeg_start_decompress(&cinfo);
|
|
|
|
if (tjDecompress(client->tjhnd, compressedData, (unsigned long)compressedLen,
|
|
|
|
if (cinfo.output_width != w || cinfo.output_height != h ||
|
|
|
|
dst, w, pitch, h, pixelSize, flags)==-1) {
|
|
|
|
cinfo.output_components != 3) {
|
|
|
|
rfbClientLog("TurboJPEG error: %s\n", tjGetErrorStr());
|
|
|
|
rfbClientLog("Tight Encoding: Wrong JPEG data received.\n");
|
|
|
|
|
|
|
|
jpeg_destroy_decompress(&cinfo);
|
|
|
|
|
|
|
|
free(compressedData);
|
|
|
|
free(compressedData);
|
|
|
|
return FALSE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
rowPointer[0] = (JSAMPROW)client->buffer;
|
|
|
|
free(compressedData);
|
|
|
|
dy = 0;
|
|
|
|
|
|
|
|
while (cinfo.output_scanline < cinfo.output_height) {
|
|
|
|
#if BPP == 16
|
|
|
|
jpeg_read_scanlines(&cinfo, rowPointer, 1);
|
|
|
|
pixelSize = BPP / 8;
|
|
|
|
if (client->jpegError) {
|
|
|
|
pitch = client->width * pixelSize;
|
|
|
|
break;
|
|
|
|
dst = &client->frameBuffer[y * pitch + x * pixelSize];
|
|
|
|
}
|
|
|
|
{
|
|
|
|
pixelPtr = (CARDBPP *)&client->buffer[RFB_BUFFER_SIZE / 2];
|
|
|
|
CARDBPP *dst16=(CARDBPP *)dst, *dst2;
|
|
|
|
for (dx = 0; dx < w; dx++) {
|
|
|
|
char *src = client->buffer;
|
|
|
|
*pixelPtr++ =
|
|
|
|
int i, j;
|
|
|
|
RGB24_TO_PIXEL(BPP, client->buffer[dx*3], client->buffer[dx*3+1], client->buffer[dx*3+2]);
|
|
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < h; j++) {
|
|
|
|
|
|
|
|
for (i = 0, dst2 = dst16; i < w; i++, dst2++, src += 3) {
|
|
|
|
|
|
|
|
*dst2 = RGB24_TO_PIXEL(BPP, src[0], src[1], src[2]);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
dst16 += client->width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
client->GotBitmap(client, (uint8_t *)&client->buffer[RFB_BUFFER_SIZE / 2], x, y + dy, w, 1);
|
|
|
|
|
|
|
|
dy++;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
if (!client->jpegError)
|
|
|
|
return TRUE;
|
|
|
|
jpeg_finish_decompress(&cinfo);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
jpeg_destroy_decompress(&cinfo);
|
|
|
|
|
|
|
|
free(compressedData);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return !client->jpegError;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
#else
|
|
|
@ -617,70 +652,6 @@ ReadCompactLen (rfbClient* client)
|
|
|
|
return len;
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* JPEG source manager functions for JPEG decompression in Tight decoder.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
|
|
JpegInitSource(j_decompress_ptr cinfo)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
rfbClient* client=(rfbClient*)cinfo->client_data;
|
|
|
|
|
|
|
|
client->jpegError = FALSE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
|
|
|
|
JpegFillInputBuffer(j_decompress_ptr cinfo)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
rfbClient* client=(rfbClient*)cinfo->client_data;
|
|
|
|
|
|
|
|
client->jpegError = TRUE;
|
|
|
|
|
|
|
|
client->jpegSrcManager->bytes_in_buffer = client->jpegBufferLen;
|
|
|
|
|
|
|
|
client->jpegSrcManager->next_input_byte = (JOCTET *)client->jpegBufferPtr;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
|
|
JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
rfbClient* client=(rfbClient*)cinfo->client_data;
|
|
|
|
|
|
|
|
if (num_bytes < 0 || num_bytes > client->jpegSrcManager->bytes_in_buffer) {
|
|
|
|
|
|
|
|
client->jpegError = TRUE;
|
|
|
|
|
|
|
|
client->jpegSrcManager->bytes_in_buffer = client->jpegBufferLen;
|
|
|
|
|
|
|
|
client->jpegSrcManager->next_input_byte = (JOCTET *)client->jpegBufferPtr;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
client->jpegSrcManager->next_input_byte += (size_t) num_bytes;
|
|
|
|
|
|
|
|
client->jpegSrcManager->bytes_in_buffer -= (size_t) num_bytes;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
|
|
JpegTermSource(j_decompress_ptr cinfo)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* nothing to do here. */
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
|
|
JpegSetSrcManager(j_decompress_ptr cinfo,
|
|
|
|
|
|
|
|
uint8_t *compressedData,
|
|
|
|
|
|
|
|
int compressedLen)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
rfbClient* client=(rfbClient*)cinfo->client_data;
|
|
|
|
|
|
|
|
client->jpegBufferPtr = compressedData;
|
|
|
|
|
|
|
|
client->jpegBufferLen = (size_t)compressedLen;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(client->jpegSrcManager == NULL)
|
|
|
|
|
|
|
|
client->jpegSrcManager = malloc(sizeof(struct jpeg_source_mgr));
|
|
|
|
|
|
|
|
client->jpegSrcManager->init_source = JpegInitSource;
|
|
|
|
|
|
|
|
client->jpegSrcManager->fill_input_buffer = JpegFillInputBuffer;
|
|
|
|
|
|
|
|
client->jpegSrcManager->skip_input_data = JpegSkipInputData;
|
|
|
|
|
|
|
|
client->jpegSrcManager->resync_to_restart = jpeg_resync_to_restart;
|
|
|
|
|
|
|
|
client->jpegSrcManager->term_source = JpegTermSource;
|
|
|
|
|
|
|
|
client->jpegSrcManager->next_input_byte = (JOCTET*)client->jpegBufferPtr;
|
|
|
|
|
|
|
|
client->jpegSrcManager->bytes_in_buffer = client->jpegBufferLen;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cinfo->src = client->jpegSrcManager;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#undef CARDBPP
|
|
|
|
#undef CARDBPP
|
|
|
|