Commit 896ca203 authored by Joel Martin's avatar Joel Martin Committed by Christian Beier

tightPng: Add initial tightPng encoding support.

http://wiki.qemu.org/VNC_Tight_PNGSigned-off-by: 's avatarJoel Martin <github@martintribe.org>
Signed-off-by: 's avatarChristian Beier <dontmind@freeshell.org>
parent 17ce0c56
...@@ -15,6 +15,7 @@ include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/ ...@@ -15,6 +15,7 @@ include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/
find_package(ZLIB) find_package(ZLIB)
find_package(JPEG) find_package(JPEG)
find_package(PNG)
find_package(SDL) find_package(SDL)
find_package(GnuTLS) find_package(GnuTLS)
find_package(Threads) find_package(Threads)
...@@ -30,6 +31,9 @@ endif(ZLIB_FOUND) ...@@ -30,6 +31,9 @@ endif(ZLIB_FOUND)
if(JPEG_FOUND) if(JPEG_FOUND)
set(LIBVNCSERVER_HAVE_LIBJPEG 1) set(LIBVNCSERVER_HAVE_LIBJPEG 1)
endif(JPEG_FOUND) endif(JPEG_FOUND)
if(PNG_FOUND)
set(LIBVNCSERVER_HAVE_LIBPNG 1)
endif(PNG_FOUND)
option(LIBVNCSERVER_ALLOW24BPP "Allow 24 bpp" ON) option(LIBVNCSERVER_ALLOW24BPP "Allow 24 bpp" ON)
if(GNUTLS_FOUND) if(GNUTLS_FOUND)
set(LIBVNCSERVER_WITH_CLIENT_TLS 1) set(LIBVNCSERVER_WITH_CLIENT_TLS 1)
...@@ -142,12 +146,21 @@ endif(ZLIB_FOUND) ...@@ -142,12 +146,21 @@ endif(ZLIB_FOUND)
if(JPEG_FOUND) if(JPEG_FOUND)
add_definitions(-DLIBVNCSERVER_HAVE_LIBJPEG) add_definitions(-DLIBVNCSERVER_HAVE_LIBJPEG)
include_directories(${JPEG_INCLUDE_DIR}) include_directories(${JPEG_INCLUDE_DIR})
set(LIBVNCSERVER_SOURCES set(TIGHT_C ${LIBVNCSERVER_DIR}/tight.c)
${LIBVNCSERVER_SOURCES}
${LIBVNCSERVER_DIR}/tight.c
)
endif(JPEG_FOUND) endif(JPEG_FOUND)
if(PNG_FOUND)
add_definitions(-DLIBVNCSERVER_HAVE_LIBPNG)
include_directories(${PNG_INCLUDE_DIR})
set(TIGHT_C ${LIBVNCSERVER_DIR}/tight.c)
endif(PNG_FOUND)
set(LIBVNCSERVER_SOURCES
${LIBVNCSERVER_SOURCES}
${TIGHT_C}
)
if(TIGHTVNC_FILETRANSFER) if(TIGHTVNC_FILETRANSFER)
set(LIBVNCSERVER_SOURCES set(LIBVNCSERVER_SOURCES
${LIBVNCSERVER_SOURCES} ${LIBVNCSERVER_SOURCES}
...@@ -174,6 +187,7 @@ target_link_libraries(vncserver ...@@ -174,6 +187,7 @@ target_link_libraries(vncserver
${ADDITIONAL_LIBS} ${ADDITIONAL_LIBS}
${ZLIB_LIBRARIES} ${ZLIB_LIBRARIES}
${JPEG_LIBRARIES} ${JPEG_LIBRARIES}
${PNG_LIBRARIES}
${SDL_LIBRARY} ${SDL_LIBRARY}
) )
......
...@@ -578,6 +578,60 @@ ftp://ftp.uu.net/graphics/jpeg/ ...@@ -578,6 +578,60 @@ ftp://ftp.uu.net/graphics/jpeg/
fi fi
fi fi
AC_ARG_WITH(png,
[ --without-png disable support for png]
[ --with-png=DIR use png include/library files in DIR],,)
# At this point:
# no png on command line with_png=""
# -with-png with_png="yes"
# -without-png with_png="no"
# -with-png=/foo/dir with_png="/foo/dir"
if test "x$with_png" != "xno"; then
if test ! -z "$with_png" -a "x$with_png" != "xyes"; then
# add user supplied directory to flags:
saved_CPPFLAGS="$CPPFLAGS"
saved_LDFLAGS="$LDFLAGS"
CPPFLAGS="$CPPFLAGS -I$with_png/include"
LDFLAGS="$LDFLAGS -L$with_png/lib"
if test "x$ld_minus_R" = "xno"; then
:
elif test "x$GCC" = "xyes"; then
# this is not complete... in general a rat's nest.
LDFLAGS="$LDFLAGS -Xlinker -R$with_png/lib"
else
LDFLAGS="$LDFLAGS -R$with_png/lib"
fi
fi
AC_CHECK_HEADER(png.h, HAVE_PNGLIB_H="true")
if test "x$HAVE_PNGLIB_H" = "xtrue"; then
AC_CHECK_LIB(png, png_create_write_struct, , HAVE_PNGLIB_H="")
fi
if test ! -z "$with_png" -a "x$with_png" != "xyes"; then
if test "x$HAVE_PNGLIB_H" != "xtrue"; then
# restore old flags on failure:
CPPFLAGS="$saved_CPPFLAGS"
LDFLAGS="$saved_LDFLAGS"
fi
fi
if test "$build_x11vnc" = "yes"; then
if test "x$HAVE_PNGLIB_H" != "xtrue"; then
AC_MSG_WARN([
==========================================================================
*** The libpng compression library was not found. ***
This may lead to reduced performance, especially over slow links.
If libpng is in a non-standard location use --with-png=DIR to
indicate the header file is in DIR/include/png.h and the library
in DIR/lib/libpng.a. A copy of libpng may be obtained from:
http://www.libpng.org/pub/png/libpng.html
==========================================================================
])
sleep 5
fi
fi
fi
AC_ARG_WITH(libz, AC_ARG_WITH(libz,
[ --without-libz disable support for deflate],,) [ --without-libz disable support for deflate],,)
AC_ARG_WITH(zlib, AC_ARG_WITH(zlib,
...@@ -654,6 +708,7 @@ AM_CONDITIONAL(WITH_TIGHTVNC_FILETRANSFER, test "$with_tightvnc_filetransfer" = ...@@ -654,6 +708,7 @@ AM_CONDITIONAL(WITH_TIGHTVNC_FILETRANSFER, test "$with_tightvnc_filetransfer" =
AM_CONDITIONAL(HAVE_LIBZ, test ! -z "$HAVE_ZLIB_H") AM_CONDITIONAL(HAVE_LIBZ, test ! -z "$HAVE_ZLIB_H")
AM_CONDITIONAL(HAVE_LIBJPEG, test ! -z "$HAVE_JPEGLIB_H") AM_CONDITIONAL(HAVE_LIBJPEG, test ! -z "$HAVE_JPEGLIB_H")
AM_CONDITIONAL(HAVE_LIBPNG, test ! -z "$HAVE_PNGLIB_H")
SDLCONFIG="sdl-config" SDLCONFIG="sdl-config"
......
...@@ -29,7 +29,11 @@ EXTRA_DIST=tableinit24.c tableinittctemplate.c tabletranstemplate.c \ ...@@ -29,7 +29,11 @@ EXTRA_DIST=tableinit24.c tableinittctemplate.c tabletranstemplate.c \
if HAVE_LIBZ if HAVE_LIBZ
ZLIBSRCS = zlib.c zrle.c zrleoutstream.c zrlepalettehelper.c ../common/zywrletemplate.c ZLIBSRCS = zlib.c zrle.c zrleoutstream.c zrlepalettehelper.c ../common/zywrletemplate.c
if HAVE_LIBJPEG if HAVE_LIBJPEG
JPEGSRCS = tight.c TIGHTSRCS = tight.c
else
if HAVE_LIBPNG
TIGHTSRCS = tight.c
endif
endif endif
endif endif
...@@ -37,7 +41,7 @@ LIB_SRCS = main.c rfbserver.c rfbregion.c auth.c sockets.c \ ...@@ -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 \ stats.c corre.c hextile.c rre.c translate.c cutpaste.c \
httpd.c cursor.c font.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 \ 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) libvncserver_la_SOURCES=$(LIB_SRCS)
......
...@@ -358,10 +358,12 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen, ...@@ -358,10 +358,12 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,
rfbScreen->clientHead = cl; rfbScreen->clientHead = cl;
UNLOCK(rfbClientListMutex); UNLOCK(rfbClientListMutex);
#ifdef LIBVNCSERVER_HAVE_LIBZ #if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG)
cl->tightQualityLevel = -1; cl->tightQualityLevel = -1;
#ifdef LIBVNCSERVER_HAVE_LIBJPEG #if defined(LIBVNCSERVER_HAVE_LIBJPEG) || defined(LIBVNCSERVER_HAVE_LIBPNG)
cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION; cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION;
#endif
#ifdef LIBVNCSERVER_HAVE_LIBJPEG
{ {
int i; int i;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
...@@ -917,6 +919,9 @@ rfbSendSupportedEncodings(rfbClientPtr cl) ...@@ -917,6 +919,9 @@ rfbSendSupportedEncodings(rfbClientPtr cl)
#endif #endif
#ifdef LIBVNCSERVER_HAVE_LIBJPEG #ifdef LIBVNCSERVER_HAVE_LIBJPEG
rfbEncodingTight, rfbEncodingTight,
#endif
#ifdef LIBVNCSERVER_HAVE_LIBPNG
rfbEncodingTightPng,
#endif #endif
rfbEncodingUltra, rfbEncodingUltra,
rfbEncodingUltraZip, rfbEncodingUltraZip,
...@@ -1937,6 +1942,9 @@ rfbProcessClientNormalMessage(rfbClientPtr cl) ...@@ -1937,6 +1942,9 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
#ifdef LIBVNCSERVER_HAVE_LIBJPEG #ifdef LIBVNCSERVER_HAVE_LIBJPEG
case rfbEncodingTight: case rfbEncodingTight:
#endif #endif
#endif
#ifdef LIBVNCSERVER_HAVE_LIBPNG
case rfbEncodingTightPng:
#endif #endif
/* The first supported encoding is the 'preferred' encoding */ /* The first supported encoding is the 'preferred' encoding */
if (cl->preferredEncoding == -1) if (cl->preferredEncoding == -1)
...@@ -2026,11 +2034,11 @@ rfbProcessClientNormalMessage(rfbClientPtr cl) ...@@ -2026,11 +2034,11 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
} }
break; break;
default: default:
#ifdef LIBVNCSERVER_HAVE_LIBZ #if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG)
if ( enc >= (uint32_t)rfbEncodingCompressLevel0 && if ( enc >= (uint32_t)rfbEncodingCompressLevel0 &&
enc <= (uint32_t)rfbEncodingCompressLevel9 ) { enc <= (uint32_t)rfbEncodingCompressLevel9 ) {
cl->zlibCompressLevel = enc & 0x0F; cl->zlibCompressLevel = enc & 0x0F;
#ifdef LIBVNCSERVER_HAVE_LIBJPEG #if defined(LIBVNCSERVER_HAVE_LIBJPEG) || defined(LIBVNCSERVER_HAVE_LIBPNG)
cl->tightCompressLevel = enc & 0x0F; cl->tightCompressLevel = enc & 0x0F;
rfbLog("Using compression level %d for client %s\n", rfbLog("Using compression level %d for client %s\n",
cl->tightCompressLevel, cl->host); cl->tightCompressLevel, cl->host);
...@@ -2754,6 +2762,28 @@ rfbSendFramebufferUpdate(rfbClientPtr cl, ...@@ -2754,6 +2762,28 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
} }
sraRgnReleaseIterator(i); i=NULL; sraRgnReleaseIterator(i); i=NULL;
#endif #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 #endif
} else { } else {
nUpdateRegionRects = sraRgnCountRects(updateRegion); nUpdateRegionRects = sraRgnCountRects(updateRegion);
...@@ -2773,6 +2803,10 @@ rfbSendFramebufferUpdate(rfbClientPtr cl, ...@@ -2773,6 +2803,10 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
/* Tight encoding counts the rectangles differently */ /* Tight encoding counts the rectangles differently */
&& cl->preferredEncoding != rfbEncodingTight && cl->preferredEncoding != rfbEncodingTight
#endif #endif
#endif
#ifdef LIBVNCSERVER_HAVE_LIBPNG
/* Tight encoding counts the rectangles differently */
&& cl->preferredEncoding != rfbEncodingTightPng
#endif #endif
&& nUpdateRegionRects>cl->screen->maxRectsPerUpdate) { && nUpdateRegionRects>cl->screen->maxRectsPerUpdate) {
sraRegion* newUpdateRegion = sraRgnBBox(updateRegion); sraRegion* newUpdateRegion = sraRgnBBox(updateRegion);
...@@ -2868,6 +2902,13 @@ rfbSendFramebufferUpdate(rfbClientPtr cl, ...@@ -2868,6 +2902,13 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
break; break;
#endif #endif
#endif #endif
#ifdef LIBVNCSERVER_HAVE_LIBPNG
case rfbEncodingTightPng:
/* TODO */
if (!rfbSendRectEncodingTightPng(cl, x, y, w, h))
goto updateFailed;
break;
#endif
#ifdef LIBVNCSERVER_HAVE_LIBZ #ifdef LIBVNCSERVER_HAVE_LIBZ
case rfbEncodingZRLE: case rfbEncodingZRLE:
case rfbEncodingZYWRLE: case rfbEncodingZYWRLE:
......
...@@ -100,6 +100,7 @@ char *encodingName(uint32_t type, char *buf, int len) { ...@@ -100,6 +100,7 @@ char *encodingName(uint32_t type, char *buf, int len) {
case rfbEncodingHextile: snprintf(buf, len, "hextile"); break; case rfbEncodingHextile: snprintf(buf, len, "hextile"); break;
case rfbEncodingZlib: snprintf(buf, len, "zlib"); break; case rfbEncodingZlib: snprintf(buf, len, "zlib"); break;
case rfbEncodingTight: snprintf(buf, len, "tight"); break; case rfbEncodingTight: snprintf(buf, len, "tight"); break;
case rfbEncodingTightPng: snprintf(buf, len, "tightPng"); break;
case rfbEncodingZlibHex: snprintf(buf, len, "zlibhex"); break; case rfbEncodingZlibHex: snprintf(buf, len, "zlibhex"); break;
case rfbEncodingUltra: snprintf(buf, len, "ultra"); break; case rfbEncodingUltra: snprintf(buf, len, "ultra"); break;
case rfbEncodingZRLE: snprintf(buf, len, "ZRLE"); break; case rfbEncodingZRLE: snprintf(buf, len, "ZRLE"); break;
......
...@@ -37,6 +37,9 @@ ...@@ -37,6 +37,9 @@
#ifdef _RPCNDR_H /* This Windows header typedefs 'boolean', jpeglib has to know */ #ifdef _RPCNDR_H /* This Windows header typedefs 'boolean', jpeglib has to know */
#define HAVE_BOOLEAN #define HAVE_BOOLEAN
#endif #endif
#ifdef LIBVNCSERVER_HAVE_LIBPNG
#include <png.h>
#endif
#include <jpeglib.h> #include <jpeglib.h>
/* Note: The following constant should not be changed. */ /* Note: The following constant should not be changed. */
...@@ -91,6 +94,25 @@ static TIGHT_CONF tightConf[10] = { ...@@ -91,6 +94,25 @@ static TIGHT_CONF tightConf[10] = {
{ 65536, 2048, 32, 8192, 9, 9, 9, 6, 200, 500, 96, 80, 200, 500 } { 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 compressLevel = 0;
static TLS int qualityLevel = 0; static TLS int qualityLevel = 0;
...@@ -146,6 +168,8 @@ void rfbTightCleanup(rfbScreenInfoPtr screen) ...@@ -146,6 +168,8 @@ void rfbTightCleanup(rfbScreenInfoPtr screen)
/* Prototypes for static functions. */ /* 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, static void FindBestSolidArea (rfbClientPtr cl, int x, int y, int w, int h,
uint32_t colorValue, int *w_ptr, int *h_ptr); uint32_t colorValue, int *w_ptr, int *h_ptr);
static void ExtendSolidArea (rfbClientPtr cl, int x, int y, int w, int h, 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); ...@@ -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 SendTightHeader (rfbClientPtr cl, int x, int y, int w, int h);
static rfbBool SendSolidRect (rfbClientPtr cl); static rfbBool SendSolidRect (rfbClientPtr cl);
static rfbBool SendMonoRect (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 w, int h); static rfbBool SendIndexedRect (rfbClientPtr cl, int x, int y, int w, int h);
static rfbBool SendFullColorRect (rfbClientPtr cl, int w, int h); static rfbBool SendFullColorRect (rfbClientPtr cl, int x, int y, int w, int h);
static rfbBool SendGradientRect (rfbClientPtr cl, 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, static rfbBool CompressData(rfbClientPtr cl, int streamId, int dataLen,
int zlibLevel, int zlibStrategy); int zlibLevel, int zlibStrategy);
...@@ -201,16 +225,20 @@ static unsigned long DetectSmoothImage32(rfbClientPtr cl, rfbPixelFormat *fmt, i ...@@ -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, static rfbBool SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h,
int quality); int quality);
static void PrepareRowForJpeg(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 PrepareRowForJpeg24(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 PrepareRowForJpeg16(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 PrepareRowForJpeg32(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 void JpegInitDestination(j_compress_ptr cinfo);
static boolean JpegEmptyOutputBuffer(j_compress_ptr cinfo); static boolean JpegEmptyOutputBuffer(j_compress_ptr cinfo);
static void JpegTermDestination(j_compress_ptr cinfo); static void JpegTermDestination(j_compress_ptr cinfo);
static void JpegSetDstManager(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. * Tight encoding implementation.
...@@ -250,6 +278,29 @@ rfbSendRectEncodingTight(rfbClientPtr cl, ...@@ -250,6 +278,29 @@ rfbSendRectEncodingTight(rfbClientPtr cl,
int y, int y,
int w, int w,
int h) 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; int nMaxRows;
uint32_t colorValue; uint32_t colorValue;
...@@ -341,7 +392,7 @@ rfbSendRectEncodingTight(rfbClientPtr cl, ...@@ -341,7 +392,7 @@ rfbSendRectEncodingTight(rfbClientPtr cl,
!SendRectSimple(cl, x, y, w, y_best-y) ) !SendRectSimple(cl, x, y, w, y_best-y) )
return FALSE; return FALSE;
if ( x_best != x && if ( x_best != x &&
!rfbSendRectEncodingTight(cl, x, y_best, !SendRectEncodingTight(cl, x, y_best,
x_best-x, h_best) ) x_best-x, h_best) )
return FALSE; return FALSE;
...@@ -364,11 +415,11 @@ rfbSendRectEncodingTight(rfbClientPtr cl, ...@@ -364,11 +415,11 @@ rfbSendRectEncodingTight(rfbClientPtr cl,
/* Send remaining rectangles (at right and bottom). */ /* Send remaining rectangles (at right and bottom). */
if ( x_best + w_best != x + w && 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) ) w-(x_best-x)-w_best, h_best) )
return FALSE; return FALSE;
if ( y_best + h_best != y + h && 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) ) w, h-(y_best-y)-h_best) )
return FALSE; return FALSE;
...@@ -629,10 +680,10 @@ SendSubrect(rfbClientPtr cl, ...@@ -629,10 +680,10 @@ SendSubrect(rfbClientPtr cl,
success = SendJpegRect(cl, x, y, w, h, success = SendJpegRect(cl, x, y, w, h,
tightConf[qualityLevel].jpegQuality); tightConf[qualityLevel].jpegQuality);
} else { } else {
success = SendGradientRect(cl, w, h); success = SendGradientRect(cl, x, y, w, h);
} }
} else { } else {
success = SendFullColorRect(cl, w, h); success = SendFullColorRect(cl, x, y, w, h);
} }
break; break;
case 1: case 1:
...@@ -641,7 +692,7 @@ SendSubrect(rfbClientPtr cl, ...@@ -641,7 +692,7 @@ SendSubrect(rfbClientPtr cl,
break; break;
case 2: case 2:
/* Two-color rectangle */ /* Two-color rectangle */
success = SendMonoRect(cl, w, h); success = SendMonoRect(cl, x, y, w, h);
break; break;
default: default:
/* Up to 256 different colors */ /* Up to 256 different colors */
...@@ -651,7 +702,7 @@ SendSubrect(rfbClientPtr cl, ...@@ -651,7 +702,7 @@ SendSubrect(rfbClientPtr cl,
success = SendJpegRect(cl, x, y, w, h, success = SendJpegRect(cl, x, y, w, h,
tightConf[qualityLevel].jpegQuality); tightConf[qualityLevel].jpegQuality);
} else { } else {
success = SendIndexedRect(cl, w, h); success = SendIndexedRect(cl, x, y, w, h);
} }
} }
return success; return success;
...@@ -675,13 +726,13 @@ SendTightHeader(rfbClientPtr cl, ...@@ -675,13 +726,13 @@ SendTightHeader(rfbClientPtr cl,
rect.r.y = Swap16IfLE(y); rect.r.y = Swap16IfLE(y);
rect.r.w = Swap16IfLE(w); rect.r.w = Swap16IfLE(w);
rect.r.h = Swap16IfLE(h); rect.r.h = Swap16IfLE(h);
rect.encoding = Swap32IfLE(rfbEncodingTight); rect.encoding = Swap32IfLE(cl->tightEncoding);
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
sz_rfbFramebufferUpdateRectHeader); sz_rfbFramebufferUpdateRectHeader);
cl->ublen += 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); sz_rfbFramebufferUpdateRectHeader + w * (cl->format.bitsPerPixel / 8) * h);
return TRUE; return TRUE;
...@@ -711,19 +762,29 @@ SendSolidRect(rfbClientPtr cl) ...@@ -711,19 +762,29 @@ SendSolidRect(rfbClientPtr cl)
memcpy (&cl->updateBuf[cl->ublen], tightBeforeBuf, len); memcpy (&cl->updateBuf[cl->ublen], tightBeforeBuf, len);
cl->ublen += len; cl->ublen += len;
rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, len+1); rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, len+1);
return TRUE; return TRUE;
} }
static rfbBool static rfbBool
SendMonoRect(rfbClientPtr cl, SendMonoRect(rfbClientPtr cl,
int x,
int y,
int w, int w,
int h) int h)
{ {
int streamId = 1; int streamId = 1;
int paletteLen, dataLen; 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 + if ( cl->ublen + TIGHT_MIN_TO_COMPRESS + 6 +
2 * cl->format.bitsPerPixel / 8 > UPDATE_BUF_SIZE ) { 2 * cl->format.bitsPerPixel / 8 > UPDATE_BUF_SIZE ) {
if (!rfbSendUpdateBuf(cl)) if (!rfbSendUpdateBuf(cl))
...@@ -754,7 +815,7 @@ SendMonoRect(rfbClientPtr cl, ...@@ -754,7 +815,7 @@ SendMonoRect(rfbClientPtr cl,
memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, paletteLen); memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, paletteLen);
cl->ublen += paletteLen; cl->ublen += paletteLen;
rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 3 + paletteLen); rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 3 + paletteLen);
break; break;
case 16: case 16:
...@@ -765,7 +826,7 @@ SendMonoRect(rfbClientPtr cl, ...@@ -765,7 +826,7 @@ SendMonoRect(rfbClientPtr cl,
memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, 4); memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, 4);
cl->ublen += 4; cl->ublen += 4;
rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 7); rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 7);
break; break;
default: default:
...@@ -773,7 +834,7 @@ SendMonoRect(rfbClientPtr cl, ...@@ -773,7 +834,7 @@ SendMonoRect(rfbClientPtr cl,
cl->updateBuf[cl->ublen++] = (char)monoBackground; cl->updateBuf[cl->ublen++] = (char)monoBackground;
cl->updateBuf[cl->ublen++] = (char)monoForeground; cl->updateBuf[cl->ublen++] = (char)monoForeground;
rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 5); rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 5);
} }
return CompressData(cl, streamId, dataLen, return CompressData(cl, streamId, dataLen,
...@@ -783,12 +844,20 @@ SendMonoRect(rfbClientPtr cl, ...@@ -783,12 +844,20 @@ SendMonoRect(rfbClientPtr cl,
static rfbBool static rfbBool
SendIndexedRect(rfbClientPtr cl, SendIndexedRect(rfbClientPtr cl,
int x,
int y,
int w, int w,
int h) int h)
{ {
int streamId = 2; int streamId = 2;
int i, entryLen; 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 + if ( cl->ublen + TIGHT_MIN_TO_COMPRESS + 6 +
paletteNumColors * cl->format.bitsPerPixel / 8 > paletteNumColors * cl->format.bitsPerPixel / 8 >
UPDATE_BUF_SIZE ) { UPDATE_BUF_SIZE ) {
...@@ -819,7 +888,7 @@ SendIndexedRect(rfbClientPtr cl, ...@@ -819,7 +888,7 @@ SendIndexedRect(rfbClientPtr cl,
memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, paletteNumColors * entryLen); memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, paletteNumColors * entryLen);
cl->ublen += paletteNumColors * entryLen; cl->ublen += paletteNumColors * entryLen;
rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 3 + paletteNumColors * entryLen); rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 3 + paletteNumColors * entryLen);
break; break;
case 16: case 16:
...@@ -832,7 +901,7 @@ SendIndexedRect(rfbClientPtr cl, ...@@ -832,7 +901,7 @@ SendIndexedRect(rfbClientPtr cl,
memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, paletteNumColors * 2); memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, paletteNumColors * 2);
cl->ublen += paletteNumColors * 2; cl->ublen += paletteNumColors * 2;
rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 3 + paletteNumColors * 2); rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 3 + paletteNumColors * 2);
break; break;
default: default:
...@@ -846,19 +915,27 @@ SendIndexedRect(rfbClientPtr cl, ...@@ -846,19 +915,27 @@ SendIndexedRect(rfbClientPtr cl,
static rfbBool static rfbBool
SendFullColorRect(rfbClientPtr cl, SendFullColorRect(rfbClientPtr cl,
int x,
int y,
int w, int w,
int h) int h)
{ {
int streamId = 0; int streamId = 0;
int len; 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 (cl->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) {
if (!rfbSendUpdateBuf(cl)) if (!rfbSendUpdateBuf(cl))
return FALSE; return FALSE;
} }
cl->updateBuf[cl->ublen++] = 0x00; /* stream id = 0, no flushing, no filter */ cl->updateBuf[cl->ublen++] = 0x00; /* stream id = 0, no flushing, no filter */
rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 1); rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1);
if (usePixelFormat24) { if (usePixelFormat24) {
Pack24(cl, tightBeforeBuf, &cl->format, w * h); Pack24(cl, tightBeforeBuf, &cl->format, w * h);
...@@ -873,6 +950,8 @@ SendFullColorRect(rfbClientPtr cl, ...@@ -873,6 +950,8 @@ SendFullColorRect(rfbClientPtr cl,
static rfbBool static rfbBool
SendGradientRect(rfbClientPtr cl, SendGradientRect(rfbClientPtr cl,
int x,
int y,
int w, int w,
int h) int h)
{ {
...@@ -880,7 +959,7 @@ SendGradientRect(rfbClientPtr cl, ...@@ -880,7 +959,7 @@ SendGradientRect(rfbClientPtr cl,
int len; int len;
if (cl->format.bitsPerPixel == 8) 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 (cl->ublen + TIGHT_MIN_TO_COMPRESS + 2 > UPDATE_BUF_SIZE) {
if (!rfbSendUpdateBuf(cl)) if (!rfbSendUpdateBuf(cl))
...@@ -892,7 +971,7 @@ SendGradientRect(rfbClientPtr cl, ...@@ -892,7 +971,7 @@ SendGradientRect(rfbClientPtr cl,
cl->updateBuf[cl->ublen++] = (streamId | rfbTightExplicitFilter) << 4; cl->updateBuf[cl->ublen++] = (streamId | rfbTightExplicitFilter) << 4;
cl->updateBuf[cl->ublen++] = rfbTightFilterGradient; cl->updateBuf[cl->ublen++] = rfbTightFilterGradient;
rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 2); rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 2);
if (usePixelFormat24) { if (usePixelFormat24) {
FilterGradient24(cl, tightBeforeBuf, &cl->format, w, h); FilterGradient24(cl, tightBeforeBuf, &cl->format, w, h);
...@@ -923,7 +1002,7 @@ CompressData(rfbClientPtr cl, ...@@ -923,7 +1002,7 @@ CompressData(rfbClientPtr cl,
if (dataLen < TIGHT_MIN_TO_COMPRESS) { if (dataLen < TIGHT_MIN_TO_COMPRESS) {
memcpy(&cl->updateBuf[cl->ublen], tightBeforeBuf, dataLen); memcpy(&cl->updateBuf[cl->ublen], tightBeforeBuf, dataLen);
cl->ublen += dataLen; cl->ublen += dataLen;
rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, dataLen); rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, dataLen);
return TRUE; return TRUE;
} }
...@@ -973,15 +1052,15 @@ static rfbBool SendCompressedData(rfbClientPtr cl, ...@@ -973,15 +1052,15 @@ static rfbBool SendCompressedData(rfbClientPtr cl,
int i, portionLen; int i, portionLen;
cl->updateBuf[cl->ublen++] = compressedLen & 0x7F; cl->updateBuf[cl->ublen++] = compressedLen & 0x7F;
rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 1); rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1);
if (compressedLen > 0x7F) { if (compressedLen > 0x7F) {
cl->updateBuf[cl->ublen-1] |= 0x80; cl->updateBuf[cl->ublen-1] |= 0x80;
cl->updateBuf[cl->ublen++] = compressedLen >> 7 & 0x7F; cl->updateBuf[cl->ublen++] = compressedLen >> 7 & 0x7F;
rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 1); rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1);
if (compressedLen > 0x3FFF) { if (compressedLen > 0x3FFF) {
cl->updateBuf[cl->ublen-1] |= 0x80; cl->updateBuf[cl->ublen-1] |= 0x80;
cl->updateBuf[cl->ublen++] = compressedLen >> 14 & 0xFF; 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, ...@@ -997,7 +1076,7 @@ static rfbBool SendCompressedData(rfbClientPtr cl,
memcpy(&cl->updateBuf[cl->ublen], &tightAfterBuf[i], portionLen); memcpy(&cl->updateBuf[cl->ublen], &tightAfterBuf[i], portionLen);
cl->ublen += portionLen; cl->ublen += portionLen;
} }
rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, compressedLen); rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, compressedLen);
return TRUE; return TRUE;
} }
...@@ -1659,11 +1738,11 @@ SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, int quality) ...@@ -1659,11 +1738,11 @@ SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, int quality)
int dy; int dy;
if (cl->screen->serverFormat.bitsPerPixel == 8) if (cl->screen->serverFormat.bitsPerPixel == 8)
return SendFullColorRect(cl, w, h); return SendFullColorRect(cl, x, y, w, h);
srcBuf = (uint8_t *)malloc(w * 3); srcBuf = (uint8_t *)malloc(w * 3);
if (srcBuf == NULL) { if (srcBuf == NULL) {
return SendFullColorRect(cl, w, h); return SendFullColorRect(cl, x, y, w, h);
} }
rowPointer[0] = srcBuf; rowPointer[0] = srcBuf;
...@@ -1683,7 +1762,7 @@ SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, int quality) ...@@ -1683,7 +1762,7 @@ SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, int quality)
jpeg_start_compress(&cinfo, TRUE); jpeg_start_compress(&cinfo, TRUE);
for (dy = 0; dy < h; dy++) { 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); jpeg_write_scanlines(&cinfo, rowPointer, 1);
if (jpegError) if (jpegError)
break; break;
...@@ -1696,7 +1775,7 @@ SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, int quality) ...@@ -1696,7 +1775,7 @@ SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, int quality)
free(srcBuf); free(srcBuf);
if (jpegError) 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 (cl->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) {
if (!rfbSendUpdateBuf(cl)) if (!rfbSendUpdateBuf(cl))
...@@ -1704,13 +1783,13 @@ SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, int quality) ...@@ -1704,13 +1783,13 @@ SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, int quality)
} }
cl->updateBuf[cl->ublen++] = (char)(rfbTightJpeg << 4); cl->updateBuf[cl->ublen++] = (char)(rfbTightJpeg << 4);
rfbStatRecordEncodingSentAdd(cl, rfbEncodingTight, 1); rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1);
return SendCompressedData(cl, jpegDstDataLen); return SendCompressedData(cl, jpegDstDataLen);
} }
static void static void
PrepareRowForJpeg(rfbClientPtr cl, PrepareRowForImg(rfbClientPtr cl,
uint8_t *dst, uint8_t *dst,
int x, int x,
int y, int y,
...@@ -1720,18 +1799,18 @@ PrepareRowForJpeg(rfbClientPtr cl, ...@@ -1720,18 +1799,18 @@ PrepareRowForJpeg(rfbClientPtr cl,
if ( cl->screen->serverFormat.redMax == 0xFF && if ( cl->screen->serverFormat.redMax == 0xFF &&
cl->screen->serverFormat.greenMax == 0xFF && cl->screen->serverFormat.greenMax == 0xFF &&
cl->screen->serverFormat.blueMax == 0xFF ) { cl->screen->serverFormat.blueMax == 0xFF ) {
PrepareRowForJpeg24(cl, dst, x, y, count); PrepareRowForImg24(cl, dst, x, y, count);
} else { } else {
PrepareRowForJpeg32(cl, dst, x, y, count); PrepareRowForImg32(cl, dst, x, y, count);
} }
} else { } else {
/* 16 bpp assumed. */ /* 16 bpp assumed. */
PrepareRowForJpeg16(cl, dst, x, y, count); PrepareRowForImg16(cl, dst, x, y, count);
} }
} }
static void static void
PrepareRowForJpeg24(rfbClientPtr cl, PrepareRowForImg24(rfbClientPtr cl,
uint8_t *dst, uint8_t *dst,
int x, int x,
int y, int y,
...@@ -1754,7 +1833,7 @@ PrepareRowForJpeg24(rfbClientPtr cl, ...@@ -1754,7 +1833,7 @@ PrepareRowForJpeg24(rfbClientPtr cl,
#define DEFINE_JPEG_GET_ROW_FUNCTION(bpp) \ #define DEFINE_JPEG_GET_ROW_FUNCTION(bpp) \
\ \
static void \ 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 *fbptr; \
uint##bpp##_t pix; \ uint##bpp##_t pix; \
int inRed, inGreen, inBlue; \ int inRed, inGreen, inBlue; \
...@@ -1822,3 +1901,161 @@ JpegSetDstManager(j_compress_ptr cinfo) ...@@ -1822,3 +1901,161 @@ JpegSetDstManager(j_compress_ptr cinfo)
cinfo->dest = &jpegDstManager; 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
...@@ -542,7 +542,9 @@ typedef struct _rfbClientRec { ...@@ -542,7 +542,9 @@ typedef struct _rfbClientRec {
struct z_stream_s compStream; struct z_stream_s compStream;
rfbBool compStreamInited; rfbBool compStreamInited;
uint32_t zlibCompressLevel; uint32_t zlibCompressLevel;
/** the quality level is also used by ZYWRLE */ #endif
#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG)
/** the quality level is also used by ZYWRLE and TightPng */
int tightQualityLevel; int tightQualityLevel;
#ifdef LIBVNCSERVER_HAVE_LIBJPEG #ifdef LIBVNCSERVER_HAVE_LIBJPEG
...@@ -550,6 +552,8 @@ typedef struct _rfbClientRec { ...@@ -550,6 +552,8 @@ typedef struct _rfbClientRec {
z_stream zsStruct[4]; z_stream zsStruct[4];
rfbBool zsActive[4]; rfbBool zsActive[4];
int zsLevel[4]; int zsLevel[4];
#endif
#if defined(LIBVNCSERVER_HAVE_LIBJPEG) || defined(LIBVNCSERVER_HAVE_LIBPNG)
int tightCompressLevel; int tightCompressLevel;
#endif #endif
#endif #endif
...@@ -624,6 +628,9 @@ typedef struct _rfbClientRec { ...@@ -624,6 +628,9 @@ typedef struct _rfbClientRec {
char *afterEncBuf; char *afterEncBuf;
int afterEncBufSize; int afterEncBufSize;
int afterEncBufLen; int afterEncBufLen;
#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG)
uint32_t tightEncoding; /* rfbEncodingTight or rfbEncodingTightPng */
#endif
} rfbClientRec, *rfbClientPtr; } rfbClientRec, *rfbClientPtr;
/** /**
...@@ -800,7 +807,7 @@ extern rfbBool rfbSendRectEncodingUltra(rfbClientPtr cl, int x,int y,int w,int h ...@@ -800,7 +807,7 @@ extern rfbBool rfbSendRectEncodingUltra(rfbClientPtr cl, int x,int y,int w,int h
extern rfbBool rfbSendRectEncodingZlib(rfbClientPtr cl, int x, int y, int w, extern rfbBool rfbSendRectEncodingZlib(rfbClientPtr cl, int x, int y, int w,
int h); int h);
#ifdef LIBVNCSERVER_HAVE_LIBJPEG #if defined(LIBVNCSERVER_HAVE_LIBJPEG) || defined(LIBVNCSERVER_HAVE_LIBPNG)
/* tight.c */ /* tight.c */
#define TIGHT_DEFAULT_COMPRESSION 6 #define TIGHT_DEFAULT_COMPRESSION 6
...@@ -808,7 +815,13 @@ extern rfbBool rfbSendRectEncodingZlib(rfbClientPtr cl, int x, int y, int w, ...@@ -808,7 +815,13 @@ extern rfbBool rfbSendRectEncodingZlib(rfbClientPtr cl, int x, int y, int w,
extern rfbBool rfbTightDisableGradient; extern rfbBool rfbTightDisableGradient;
extern int rfbNumCodedRectsTight(rfbClientPtr cl, int x,int y,int w,int h); extern int rfbNumCodedRectsTight(rfbClientPtr cl, int x,int y,int w,int h);
#if defined(LIBVNCSERVER_HAVE_LIBJPEG)
extern rfbBool rfbSendRectEncodingTight(rfbClientPtr cl, int x,int y,int w,int h); extern rfbBool rfbSendRectEncodingTight(rfbClientPtr cl, int x,int y,int w,int h);
#endif
#if defined(LIBVNCSERVER_HAVE_LIBPNG)
extern rfbBool rfbSendRectEncodingTightPng(rfbClientPtr cl, int x,int y,int w,int h);
#endif
#endif #endif
#endif #endif
......
...@@ -18,6 +18,9 @@ ...@@ -18,6 +18,9 @@
/* Define to 1 if you have the `jpeg' library (-ljpeg). */ /* Define to 1 if you have the `jpeg' library (-ljpeg). */
#cmakedefine LIBVNCSERVER_HAVE_LIBJPEG 1 #cmakedefine LIBVNCSERVER_HAVE_LIBJPEG 1
/* Define if you have the `png' library (-lpng). */
#cmakedefine LIBVNCSERVER_HAVE_LIBPNG 1
/* Define to 1 if you have the `pthread' library (-lpthread). */ /* Define to 1 if you have the `pthread' library (-lpthread). */
#cmakedefine LIBVNCSERVER_HAVE_LIBPTHREAD 1 #cmakedefine LIBVNCSERVER_HAVE_LIBPTHREAD 1
......
...@@ -434,6 +434,7 @@ typedef struct { ...@@ -434,6 +434,7 @@ typedef struct {
#define rfbEncodingHextile 5 #define rfbEncodingHextile 5
#define rfbEncodingZlib 6 #define rfbEncodingZlib 6
#define rfbEncodingTight 7 #define rfbEncodingTight 7
#define rfbEncodingTightPng 0xFFFFFEFC /* -260 */
#define rfbEncodingZlibHex 8 #define rfbEncodingZlibHex 8
#define rfbEncodingUltra 9 #define rfbEncodingUltra 9
#define rfbEncodingZRLE 16 #define rfbEncodingZRLE 16
...@@ -704,7 +705,10 @@ typedef struct { ...@@ -704,7 +705,10 @@ typedef struct {
#ifdef LIBVNCSERVER_HAVE_LIBZ #ifdef LIBVNCSERVER_HAVE_LIBZ
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Tight Encoding. * Tight and TightPng Encoding.
*
*-- TightPng is like Tight but basic compression is not used, instead PNG
* data is sent.
* *
*-- The first byte of each Tight-encoded rectangle is a "compression control *-- The first byte of each Tight-encoded rectangle is a "compression control
* byte". Its format is as follows (bit 0 is the least significant one): * byte". Its format is as follows (bit 0 is the least significant one):
...@@ -715,8 +719,9 @@ typedef struct { ...@@ -715,8 +719,9 @@ typedef struct {
* bit 3: if 1, then compression stream 3 should be reset; * bit 3: if 1, then compression stream 3 should be reset;
* bits 7-4: if 1000 (0x08), then the compression type is "fill", * bits 7-4: if 1000 (0x08), then the compression type is "fill",
* if 1001 (0x09), then the compression type is "jpeg", * if 1001 (0x09), then the compression type is "jpeg",
* if 1001 (0x0A), then the compression type is "png",
* if 0xxx, then the compression type is "basic", * if 0xxx, then the compression type is "basic",
* values greater than 1001 are not valid. * values greater than 1010 are not valid.
* *
* If the compression type is "basic", then bits 6..4 of the * If the compression type is "basic", then bits 6..4 of the
* compression control byte (those xxx in 0xxx) specify the following: * compression control byte (those xxx in 0xxx) specify the following:
...@@ -726,17 +731,17 @@ typedef struct { ...@@ -726,17 +731,17 @@ typedef struct {
* bit 6: if 1, then a "filter id" byte is following this byte. * bit 6: if 1, then a "filter id" byte is following this byte.
* *
*-- The data that follows after the compression control byte described *-- The data that follows after the compression control byte described
* above depends on the compression type ("fill", "jpeg" or "basic"). * above depends on the compression type ("fill", "jpeg", "png" or "basic").
* *
*-- If the compression type is "fill", then the only pixel value follows, in *-- If the compression type is "fill", then the only pixel value follows, in
* client pixel format (see NOTE 1). This value applies to all pixels of the * client pixel format (see NOTE 1). This value applies to all pixels of the
* rectangle. * rectangle.
* *
*-- If the compression type is "jpeg", the following data stream looks like *-- If the compression type is "jpeg" or "png", the following data stream
* this: * looks like this:
* *
* 1..3 bytes: data size (N) in compact representation; * 1..3 bytes: data size (N) in compact representation;
* N bytes: JPEG image. * N bytes: JPEG or PNG image.
* *
* Data size is compactly represented in one, two or three bytes, according * Data size is compactly represented in one, two or three bytes, according
* to the following scheme: * to the following scheme:
...@@ -817,7 +822,7 @@ typedef struct { ...@@ -817,7 +822,7 @@ typedef struct {
*-- NOTE 2. The decoder must reset compression streams' states before *-- NOTE 2. The decoder must reset compression streams' states before
* decoding the rectangle, if some of bits 0,1,2,3 in the compression control * decoding the rectangle, if some of bits 0,1,2,3 in the compression control
* byte are set to 1. Note that the decoder must reset zlib streams even if * byte are set to 1. Note that the decoder must reset zlib streams even if
* the compression type is "fill" or "jpeg". * the compression type is "fill", "jpeg" or "png".
* *
*-- NOTE 3. The "gradient" filter and "jpeg" compression may be used only *-- NOTE 3. The "gradient" filter and "jpeg" compression may be used only
* when bits-per-pixel value is either 16 or 32, not 8. * when bits-per-pixel value is either 16 or 32, not 8.
...@@ -831,7 +836,8 @@ typedef struct { ...@@ -831,7 +836,8 @@ typedef struct {
#define rfbTightExplicitFilter 0x04 #define rfbTightExplicitFilter 0x04
#define rfbTightFill 0x08 #define rfbTightFill 0x08
#define rfbTightJpeg 0x09 #define rfbTightJpeg 0x09
#define rfbTightMaxSubencoding 0x09 #define rfbTightPng 0x0A
#define rfbTightMaxSubencoding 0x0A
/* Filters to improve compression efficiency */ /* Filters to improve compression efficiency */
#define rfbTightFilterCopy 0x00 #define rfbTightFilterCopy 0x00
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment