diff options
Diffstat (limited to 'libvncserver')
-rw-r--r-- | libvncserver/Makefile.am | 8 | ||||
-rw-r--r-- | libvncserver/rfbserver.c | 49 | ||||
-rw-r--r-- | libvncserver/stats.c | 1 | ||||
-rw-r--r-- | libvncserver/tight.c | 321 |
4 files changed, 331 insertions, 48 deletions
diff --git a/libvncserver/Makefile.am b/libvncserver/Makefile.am index 538617f..a685ed1 100644 --- a/libvncserver/Makefile.am +++ b/libvncserver/Makefile.am @@ -29,7 +29,11 @@ EXTRA_DIST=tableinit24.c tableinittctemplate.c tabletranstemplate.c \ if HAVE_LIBZ ZLIBSRCS = zlib.c zrle.c zrleoutstream.c zrlepalettehelper.c ../common/zywrletemplate.c if HAVE_LIBJPEG -JPEGSRCS = tight.c +TIGHTSRCS = tight.c +else +if HAVE_LIBPNG +TIGHTSRCS = tight.c +endif endif endif @@ -37,7 +41,7 @@ LIB_SRCS = main.c rfbserver.c rfbregion.c auth.c sockets.c \ stats.c corre.c hextile.c rre.c translate.c cutpaste.c \ httpd.c cursor.c font.c \ draw.c selbox.c ../common/d3des.c ../common/vncauth.c cargs.c ../common/minilzo.c ultra.c scale.c \ - $(ZLIBSRCS) $(JPEGSRCS) $(TIGHTVNCFILETRANSFERSRCS) + $(ZLIBSRCS) $(TIGHTSRCS) $(TIGHTVNCFILETRANSFERSRCS) libvncserver_la_SOURCES=$(LIB_SRCS) diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c index 8f0e390..587a2f0 100644 --- a/libvncserver/rfbserver.c +++ b/libvncserver/rfbserver.c @@ -358,10 +358,12 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen, rfbScreen->clientHead = cl; UNLOCK(rfbClientListMutex); -#ifdef LIBVNCSERVER_HAVE_LIBZ +#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG) cl->tightQualityLevel = -1; -#ifdef LIBVNCSERVER_HAVE_LIBJPEG +#if defined(LIBVNCSERVER_HAVE_LIBJPEG) || defined(LIBVNCSERVER_HAVE_LIBPNG) cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION; +#endif +#ifdef LIBVNCSERVER_HAVE_LIBJPEG { int i; for (i = 0; i < 4; i++) @@ -918,6 +920,9 @@ rfbSendSupportedEncodings(rfbClientPtr cl) #ifdef LIBVNCSERVER_HAVE_LIBJPEG rfbEncodingTight, #endif +#ifdef LIBVNCSERVER_HAVE_LIBPNG + rfbEncodingTightPng, +#endif rfbEncodingUltra, rfbEncodingUltraZip, rfbEncodingXCursor, @@ -1938,6 +1943,9 @@ rfbProcessClientNormalMessage(rfbClientPtr cl) case rfbEncodingTight: #endif #endif +#ifdef LIBVNCSERVER_HAVE_LIBPNG + case rfbEncodingTightPng: +#endif /* The first supported encoding is the 'preferred' encoding */ if (cl->preferredEncoding == -1) cl->preferredEncoding = enc; @@ -2026,11 +2034,11 @@ rfbProcessClientNormalMessage(rfbClientPtr cl) } break; default: -#ifdef LIBVNCSERVER_HAVE_LIBZ +#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG) if ( enc >= (uint32_t)rfbEncodingCompressLevel0 && enc <= (uint32_t)rfbEncodingCompressLevel9 ) { cl->zlibCompressLevel = enc & 0x0F; -#ifdef LIBVNCSERVER_HAVE_LIBJPEG +#if defined(LIBVNCSERVER_HAVE_LIBJPEG) || defined(LIBVNCSERVER_HAVE_LIBPNG) cl->tightCompressLevel = enc & 0x0F; rfbLog("Using compression level %d for client %s\n", cl->tightCompressLevel, cl->host); @@ -2755,6 +2763,28 @@ rfbSendFramebufferUpdate(rfbClientPtr cl, sraRgnReleaseIterator(i); i=NULL; #endif #endif +#ifdef LIBVNCSERVER_HAVE_LIBPNG + } else if (cl->preferredEncoding == rfbEncodingTightPng) { + nUpdateRegionRects = 0; + + for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){ + int x = rect.x1; + int y = rect.y1; + int w = rect.x2 - x; + int h = rect.y2 - y; + int n; + /* We need to count the number of rects in the scaled screen */ + if (cl->screen!=cl->scaledScreen) + rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate"); + n = rfbNumCodedRectsTight(cl, x, y, w, h); + if (n == 0) { + nUpdateRegionRects = 0xFFFF; + break; + } + nUpdateRegionRects += n; + } + sraRgnReleaseIterator(i); i=NULL; +#endif } else { nUpdateRegionRects = sraRgnCountRects(updateRegion); } @@ -2774,6 +2804,10 @@ rfbSendFramebufferUpdate(rfbClientPtr cl, && cl->preferredEncoding != rfbEncodingTight #endif #endif +#ifdef LIBVNCSERVER_HAVE_LIBPNG + /* Tight encoding counts the rectangles differently */ + && cl->preferredEncoding != rfbEncodingTightPng +#endif && nUpdateRegionRects>cl->screen->maxRectsPerUpdate) { sraRegion* newUpdateRegion = sraRgnBBox(updateRegion); sraRgnDestroy(updateRegion); @@ -2868,6 +2902,13 @@ rfbSendFramebufferUpdate(rfbClientPtr cl, break; #endif #endif +#ifdef LIBVNCSERVER_HAVE_LIBPNG + case rfbEncodingTightPng: + /* TODO */ + if (!rfbSendRectEncodingTightPng(cl, x, y, w, h)) + goto updateFailed; + break; +#endif #ifdef LIBVNCSERVER_HAVE_LIBZ case rfbEncodingZRLE: case rfbEncodingZYWRLE: diff --git a/libvncserver/stats.c b/libvncserver/stats.c index 6dab13b..39de1c6 100644 --- a/libvncserver/stats.c +++ b/libvncserver/stats.c @@ -100,6 +100,7 @@ char *encodingName(uint32_t type, char *buf, int len) { case rfbEncodingHextile: snprintf(buf, len, "hextile"); break; case rfbEncodingZlib: snprintf(buf, len, "zlib"); break; case rfbEncodingTight: snprintf(buf, len, "tight"); break; + case rfbEncodingTightPng: snprintf(buf, len, "tightPng"); break; case rfbEncodingZlibHex: snprintf(buf, len, "zlibhex"); break; case rfbEncodingUltra: snprintf(buf, len, "ultra"); break; case rfbEncodingZRLE: snprintf(buf, len, "ZRLE"); break; diff --git a/libvncserver/tight.c b/libvncserver/tight.c index bb033c3..83a25e3 100644 --- a/libvncserver/tight.c +++ b/libvncserver/tight.c @@ -37,6 +37,9 @@ #ifdef _RPCNDR_H /* This Windows header typedefs 'boolean', jpeglib has to know */ #define HAVE_BOOLEAN #endif +#ifdef LIBVNCSERVER_HAVE_LIBPNG +#include <png.h> +#endif #include <jpeglib.h> /* Note: The following constant should not be changed. */ @@ -91,6 +94,25 @@ static TIGHT_CONF tightConf[10] = { { 65536, 2048, 32, 8192, 9, 9, 9, 6, 200, 500, 96, 80, 200, 500 } }; +#ifdef LIBVNCSERVER_HAVE_LIBPNG +typedef struct TIGHT_PNG_CONF_s { + int png_zlib_level, png_filters; +} TIGHT_PNG_CONF; + +static TIGHT_PNG_CONF tightPngConf[10] = { + { 0, PNG_NO_FILTERS }, + { 1, PNG_NO_FILTERS }, + { 2, PNG_NO_FILTERS }, + { 3, PNG_NO_FILTERS }, + { 4, PNG_NO_FILTERS }, + { 5, PNG_ALL_FILTERS }, + { 6, PNG_ALL_FILTERS }, + { 7, PNG_ALL_FILTERS }, + { 8, PNG_ALL_FILTERS }, + { 9, PNG_ALL_FILTERS }, +}; +#endif + static TLS int compressLevel = 0; static TLS int qualityLevel = 0; @@ -146,6 +168,8 @@ void rfbTightCleanup(rfbScreenInfoPtr screen) /* Prototypes for static functions. */ +static rfbBool SendRectEncodingTight(rfbClientPtr cl, int x, int y, + int w, int h); static void FindBestSolidArea (rfbClientPtr cl, int x, int y, int w, int h, uint32_t colorValue, int *w_ptr, int *h_ptr); static void ExtendSolidArea (rfbClientPtr cl, int x, int y, int w, int h, @@ -165,10 +189,10 @@ static rfbBool SendSubrect (rfbClientPtr cl, int x, int y, int w, int h); static rfbBool SendTightHeader (rfbClientPtr cl, int x, int y, int w, int h); static rfbBool SendSolidRect (rfbClientPtr cl); -static rfbBool SendMonoRect (rfbClientPtr cl, int w, int h); -static rfbBool SendIndexedRect (rfbClientPtr cl, int w, int h); -static rfbBool SendFullColorRect (rfbClientPtr cl, int w, int h); -static rfbBool SendGradientRect (rfbClientPtr cl, int w, int h); +static rfbBool SendMonoRect (rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool SendIndexedRect (rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool SendFullColorRect (rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool SendGradientRect (rfbClientPtr cl, int x, int y, int w, int h); static rfbBool CompressData(rfbClientPtr cl, int streamId, int dataLen, int zlibLevel, int zlibStrategy); @@ -201,16 +225,20 @@ static unsigned long DetectSmoothImage32(rfbClientPtr cl, rfbPixelFormat *fmt, i static rfbBool SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, int quality); -static void PrepareRowForJpeg(rfbClientPtr cl, uint8_t *dst, int x, int y, int count); -static void PrepareRowForJpeg24(rfbClientPtr cl, uint8_t *dst, int x, int y, int count); -static void PrepareRowForJpeg16(rfbClientPtr cl, uint8_t *dst, int x, int y, int count); -static void PrepareRowForJpeg32(rfbClientPtr cl, uint8_t *dst, int x, int y, int count); +static void PrepareRowForImg(rfbClientPtr cl, uint8_t *dst, int x, int y, int count); +static void PrepareRowForImg24(rfbClientPtr cl, uint8_t *dst, int x, int y, int count); +static void PrepareRowForImg16(rfbClientPtr cl, uint8_t *dst, int x, int y, int count); +static void PrepareRowForImg32(rfbClientPtr cl, uint8_t *dst, int x, int y, int count); static void JpegInitDestination(j_compress_ptr cinfo); static boolean JpegEmptyOutputBuffer(j_compress_ptr cinfo); static void JpegTermDestination(j_compress_ptr cinfo); static void JpegSetDstManager(j_compress_ptr cinfo); +#ifdef LIBVNCSERVER_HAVE_LIBPNG +static rfbBool SendPngRect(rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool CanSendPngRect(rfbClientPtr cl, int w, int h); +#endif /* * Tight encoding implementation. @@ -251,6 +279,29 @@ rfbSendRectEncodingTight(rfbClientPtr cl, int w, int h) { + cl->tightEncoding = rfbEncodingTight; + return SendRectEncodingTight(cl, x, y, w, h); +} + +rfbBool +rfbSendRectEncodingTightPng(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + cl->tightEncoding = rfbEncodingTightPng; + return SendRectEncodingTight(cl, x, y, w, h); +} + + +rfbBool +SendRectEncodingTight(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ int nMaxRows; uint32_t colorValue; int dx, dy, dw, dh; @@ -341,7 +392,7 @@ rfbSendRectEncodingTight(rfbClientPtr cl, !SendRectSimple(cl, x, y, w, y_best-y) ) return FALSE; if ( x_best != x && - !rfbSendRectEncodingTight(cl, x, y_best, + !SendRectEncodingTight(cl, x, y_best, x_best-x, h_best) ) return FALSE; @@ -364,11 +415,11 @@ rfbSendRectEncodingTight(rfbClientPtr cl, /* Send remaining rectangles (at right and bottom). */ if ( x_best + w_best != x + w && - !rfbSendRectEncodingTight(cl, x_best+w_best, y_best, + !SendRectEncodingTight(cl, x_best+w_best, y_best, w-(x_best-x)-w_best, h_best) ) return FALSE; if ( y_best + h_best != y + h && - !rfbSendRectEncodingTight(cl, x, y_best+h_best, + !SendRectEncodingTight(cl, x, y_best+h_best, w, h-(y_best-y)-h_best) ) return FALSE; @@ -629,10 +680,10 @@ SendSubrect(rfbClientPtr cl, success = SendJpegRect(cl, x, y, w, h, tightConf[qualityLevel].jpegQuality); } else { - success = SendGradientRect(cl, w, h); + success = SendGradientRect(cl, x, y, w, h); } } else { - success = SendFullColorRect(cl, w, h); + success = SendFullColorRect(cl, x, y, w, h); } break; case 1: @@ -641,7 +692,7 @@ SendSubrect(rfbClientPtr cl, break; case 2: /* Two-color rectangle */ - success = SendMonoRect(cl, w, h); + success = SendMonoRect(cl, x, y, w, h); break; default: /* Up to 256 different colors */ @@ -651,7 +702,7 @@ SendSubrect(rfbClientPtr cl, success = SendJpegRect(cl, x, y, w, h, tightConf[qualityLevel].jpegQuality); } else { - success = SendIndexedRect(cl, w, h); + success = SendIndexedRect(cl, x, y, w, h); } } return success; @@ -675,13 +726,13 @@ SendTightHeader(rfbClientPtr cl, rect.r.y = Swap16IfLE(y); rect.r.w = Swap16IfLE(w); rect.r.h = Swap16IfLE(h); - rect.encoding = Swap32IfLE(rfbEncodingTight); + rect.encoding = Swap32IfLE(cl->tightEncoding); memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, sz_rfbFramebufferUpdateRectHeader); cl->ublen += sz_rfbFramebufferUpdateRectHeader; - rfbStatRecordEncodingSent(cl, rfbEncodingTight, sz_rfbFramebufferUpdateRectHeader, + rfbStatRecordEncodingSent(cl, cl->tightEncoding, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader + w * (cl->format.bitsPerPixel / 8) * h); return TRUE; @@ -711,19 +762,29 @@ SendSolidRect(rfbClientPtr cl) memcpy (&cl->updateBuf[cl->ublen], tightBeforeBuf, len); cl->ublen += len; - rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, len+1); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, len+1); return TRUE; } static rfbBool SendMonoRect(rfbClientPtr cl, + int x, + int y, int w, int h) { int streamId = 1; int paletteLen, dataLen; +#ifdef LIBVNCSERVER_HAVE_LIBPNG + if (CanSendPngRect(cl, w, h)) { + /* TODO: setup palette maybe */ + return SendPngRect(cl, x, y, w, h); + /* TODO: destroy palette maybe */ + } +#endif + if ( cl->ublen + TIGHT_MIN_TO_COMPRESS + 6 + 2 * cl->format.bitsPerPixel / 8 > UPDATE_BUF_SIZE ) { if (!rfbSendUpdateBuf(cl)) @@ -754,7 +815,7 @@ SendMonoRect(rfbClientPtr cl, memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, paletteLen); cl->ublen += paletteLen; - rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 3 + paletteLen); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 3 + paletteLen); break; case 16: @@ -765,7 +826,7 @@ SendMonoRect(rfbClientPtr cl, memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, 4); cl->ublen += 4; - rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 7); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 7); break; default: @@ -773,7 +834,7 @@ SendMonoRect(rfbClientPtr cl, cl->updateBuf[cl->ublen++] = (char)monoBackground; cl->updateBuf[cl->ublen++] = (char)monoForeground; - rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 5); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 5); } return CompressData(cl, streamId, dataLen, @@ -783,12 +844,20 @@ SendMonoRect(rfbClientPtr cl, static rfbBool SendIndexedRect(rfbClientPtr cl, + int x, + int y, int w, int h) { int streamId = 2; int i, entryLen; +#ifdef LIBVNCSERVER_HAVE_LIBPNG + if (CanSendPngRect(cl, w, h)) { + return SendPngRect(cl, x, y, w, h); + } +#endif + if ( cl->ublen + TIGHT_MIN_TO_COMPRESS + 6 + paletteNumColors * cl->format.bitsPerPixel / 8 > UPDATE_BUF_SIZE ) { @@ -819,7 +888,7 @@ SendIndexedRect(rfbClientPtr cl, memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, paletteNumColors * entryLen); cl->ublen += paletteNumColors * entryLen; - rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 3 + paletteNumColors * entryLen); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 3 + paletteNumColors * entryLen); break; case 16: @@ -832,7 +901,7 @@ SendIndexedRect(rfbClientPtr cl, memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, paletteNumColors * 2); cl->ublen += paletteNumColors * 2; - rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 3 + paletteNumColors * 2); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 3 + paletteNumColors * 2); break; default: @@ -846,19 +915,27 @@ SendIndexedRect(rfbClientPtr cl, static rfbBool SendFullColorRect(rfbClientPtr cl, + int x, + int y, int w, int h) { int streamId = 0; int len; +#ifdef LIBVNCSERVER_HAVE_LIBPNG + if (CanSendPngRect(cl, w, h)) { + return SendPngRect(cl, x, y, w, h); + } +#endif + if (cl->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) { if (!rfbSendUpdateBuf(cl)) return FALSE; } cl->updateBuf[cl->ublen++] = 0x00; /* stream id = 0, no flushing, no filter */ - rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 1); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); if (usePixelFormat24) { Pack24(cl, tightBeforeBuf, &cl->format, w * h); @@ -873,6 +950,8 @@ SendFullColorRect(rfbClientPtr cl, static rfbBool SendGradientRect(rfbClientPtr cl, + int x, + int y, int w, int h) { @@ -880,7 +959,7 @@ SendGradientRect(rfbClientPtr cl, int len; if (cl->format.bitsPerPixel == 8) - return SendFullColorRect(cl, w, h); + return SendFullColorRect(cl, x, y, w, h); if (cl->ublen + TIGHT_MIN_TO_COMPRESS + 2 > UPDATE_BUF_SIZE) { if (!rfbSendUpdateBuf(cl)) @@ -892,7 +971,7 @@ SendGradientRect(rfbClientPtr cl, cl->updateBuf[cl->ublen++] = (streamId | rfbTightExplicitFilter) << 4; cl->updateBuf[cl->ublen++] = rfbTightFilterGradient; - rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 2); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 2); if (usePixelFormat24) { FilterGradient24(cl, tightBeforeBuf, &cl->format, w, h); @@ -923,7 +1002,7 @@ CompressData(rfbClientPtr cl, if (dataLen < TIGHT_MIN_TO_COMPRESS) { memcpy(&cl->updateBuf[cl->ublen], tightBeforeBuf, dataLen); cl->ublen += dataLen; - rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, dataLen); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, dataLen); return TRUE; } @@ -973,15 +1052,15 @@ static rfbBool SendCompressedData(rfbClientPtr cl, int i, portionLen; cl->updateBuf[cl->ublen++] = compressedLen & 0x7F; - rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 1); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); if (compressedLen > 0x7F) { cl->updateBuf[cl->ublen-1] |= 0x80; cl->updateBuf[cl->ublen++] = compressedLen >> 7 & 0x7F; - rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 1); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); if (compressedLen > 0x3FFF) { cl->updateBuf[cl->ublen-1] |= 0x80; cl->updateBuf[cl->ublen++] = compressedLen >> 14 & 0xFF; - rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 1); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); } } @@ -997,7 +1076,7 @@ static rfbBool SendCompressedData(rfbClientPtr cl, memcpy(&cl->updateBuf[cl->ublen], &tightAfterBuf[i], portionLen); cl->ublen += portionLen; } - rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, compressedLen); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, compressedLen); return TRUE; } @@ -1659,11 +1738,11 @@ SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, int quality) int dy; if (cl->screen->serverFormat.bitsPerPixel == 8) - return SendFullColorRect(cl, w, h); + return SendFullColorRect(cl, x, y, w, h); srcBuf = (uint8_t *)malloc(w * 3); if (srcBuf == NULL) { - return SendFullColorRect(cl, w, h); + return SendFullColorRect(cl, x, y, w, h); } rowPointer[0] = srcBuf; @@ -1683,7 +1762,7 @@ SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, int quality) jpeg_start_compress(&cinfo, TRUE); for (dy = 0; dy < h; dy++) { - PrepareRowForJpeg(cl, srcBuf, x, y + dy, w); + PrepareRowForImg(cl, srcBuf, x, y + dy, w); jpeg_write_scanlines(&cinfo, rowPointer, 1); if (jpegError) break; @@ -1696,7 +1775,7 @@ SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, int quality) free(srcBuf); if (jpegError) - return SendFullColorRect(cl, w, h); + return SendFullColorRect(cl, x, y, w, h); if (cl->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) { if (!rfbSendUpdateBuf(cl)) @@ -1704,13 +1783,13 @@ SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, int quality) } cl->updateBuf[cl->ublen++] = (char)(rfbTightJpeg << 4); - rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 1); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); return SendCompressedData(cl, jpegDstDataLen); } static void -PrepareRowForJpeg(rfbClientPtr cl, +PrepareRowForImg(rfbClientPtr cl, uint8_t *dst, int x, int y, @@ -1720,18 +1799,18 @@ PrepareRowForJpeg(rfbClientPtr cl, if ( cl->screen->serverFormat.redMax == 0xFF && cl->screen->serverFormat.greenMax == 0xFF && cl->screen->serverFormat.blueMax == 0xFF ) { - PrepareRowForJpeg24(cl, dst, x, y, count); + PrepareRowForImg24(cl, dst, x, y, count); } else { - PrepareRowForJpeg32(cl, dst, x, y, count); + PrepareRowForImg32(cl, dst, x, y, count); } } else { /* 16 bpp assumed. */ - PrepareRowForJpeg16(cl, dst, x, y, count); + PrepareRowForImg16(cl, dst, x, y, count); } } static void -PrepareRowForJpeg24(rfbClientPtr cl, +PrepareRowForImg24(rfbClientPtr cl, uint8_t *dst, int x, int y, @@ -1754,7 +1833,7 @@ PrepareRowForJpeg24(rfbClientPtr cl, #define DEFINE_JPEG_GET_ROW_FUNCTION(bpp) \ \ static void \ -PrepareRowForJpeg##bpp(rfbClientPtr cl, uint8_t *dst, int x, int y, int count) { \ +PrepareRowForImg##bpp(rfbClientPtr cl, uint8_t *dst, int x, int y, int count) { \ uint##bpp##_t *fbptr; \ uint##bpp##_t pix; \ int inRed, inGreen, inBlue; \ @@ -1822,3 +1901,161 @@ JpegSetDstManager(j_compress_ptr cinfo) cinfo->dest = &jpegDstManager; } +/* + * PNG compression stuff. + */ + +#ifdef LIBVNCSERVER_HAVE_LIBPNG + +static TLS int pngDstDataLen = 0; + +static rfbBool CanSendPngRect(rfbClientPtr cl, int w, int h) { + if (cl->tightEncoding != rfbEncodingTightPng) { + return FALSE; + } + + if ( cl->screen->serverFormat.bitsPerPixel == 8 || + cl->format.bitsPerPixel == 8) { + return FALSE; + } + + return TRUE; +} + +static void pngWriteData(png_structp png_ptr, png_bytep data, + png_size_t length) +{ +#if 0 + rfbClientPtr cl = png_get_io_ptr(png_ptr); + + buffer_reserve(&vs->tight.png, vs->tight.png.offset + length); + memcpy(vs->tight.png.buffer + vs->tight.png.offset, data, length); +#endif + memcpy(tightAfterBuf + pngDstDataLen, data, length); + + pngDstDataLen += length; +} + +static void pngFlushData(png_structp png_ptr) +{ +} + + +static void *pngMalloc(png_structp png_ptr, png_size_t size) +{ + return malloc(size); +} + +static void pngFree(png_structp png_ptr, png_voidp ptr) +{ + free(ptr); +} + +static rfbBool SendPngRect(rfbClientPtr cl, int x, int y, int w, int h) { + /* rfbLog(">> SendPngRect x:%d, y:%d, w:%d, h:%d\n", x, y, w, h); */ + + png_byte color_type; + png_structp png_ptr; + png_infop info_ptr; + png_colorp png_palette = NULL; + int level = tightPngConf[cl->tightCompressLevel].png_zlib_level; + int filters = tightPngConf[cl->tightCompressLevel].png_filters; + uint8_t *buf; + int dy; + + pngDstDataLen = 0; + + png_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, + NULL, pngMalloc, pngFree); + + if (png_ptr == NULL) + return FALSE; + + info_ptr = png_create_info_struct(png_ptr); + + if (info_ptr == NULL) { + png_destroy_write_struct(&png_ptr, NULL); + return FALSE; + } + + png_set_write_fn(png_ptr, (void *) cl, pngWriteData, pngFlushData); + png_set_compression_level(png_ptr, level); + png_set_filter(png_ptr, PNG_FILTER_TYPE_DEFAULT, filters); + +#if 0 + /* TODO: */ + if (palette) { + color_type = PNG_COLOR_TYPE_PALETTE; + } else { + color_type = PNG_COLOR_TYPE_RGB; + } +#else + color_type = PNG_COLOR_TYPE_RGB; +#endif + png_set_IHDR(png_ptr, info_ptr, w, h, + 8, color_type, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + +#if 0 + if (color_type == PNG_COLOR_TYPE_PALETTE) { + struct palette_cb_priv priv; + + png_palette = pngMalloc(png_ptr, sizeof(*png_palette) * + palette_size(palette)); + + priv.vs = vs; + priv.png_palette = png_palette; + palette_iter(palette, write_png_palette, &priv); + + png_set_PLTE(png_ptr, info_ptr, png_palette, palette_size(palette)); + + offset = vs->tight.tight.offset; + if (vs->clientds.pf.bytes_per_pixel == 4) { + tight_encode_indexed_rect32(vs->tight.tight.buffer, w * h, palette); + } else { + tight_encode_indexed_rect16(vs->tight.tight.buffer, w * h, palette); + } + } + + buffer_reserve(&vs->tight.png, 2048); +#endif + + png_write_info(png_ptr, info_ptr); + buf = malloc(w * 3); + for (dy = 0; dy < h; dy++) + { +#if 0 + if (color_type == PNG_COLOR_TYPE_PALETTE) { + memcpy(buf, vs->tight.tight.buffer + (dy * w), w); + } else { + PrepareRowForImg(cl, buf, x, y + dy, w); + } +#else + PrepareRowForImg(cl, buf, x, y + dy, w); +#endif + png_write_row(png_ptr, buf); + } + free(buf); + + png_write_end(png_ptr, NULL); + + if (color_type == PNG_COLOR_TYPE_PALETTE) { + pngFree(png_ptr, png_palette); + } + + png_destroy_write_struct(&png_ptr, &info_ptr); + + /* done v */ + + if (cl->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + cl->updateBuf[cl->ublen++] = (char)(rfbTightPng << 4); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); + + /* rfbLog("<< SendPngRect\n"); */ + return SendCompressedData(cl, pngDstDataLen); +} +#endif |