diff options
author | runge <runge> | 2004-07-02 01:35:59 +0000 |
---|---|---|
committer | runge <runge> | 2004-07-02 01:35:59 +0000 |
commit | 515dbae42a295fc90bec4dc13f91338cb8135e70 (patch) | |
tree | 9fba0a6f6abf8c2eaf71c8e8755d9219293f2045 | |
parent | b68e3879493c12777ad375742e6871acae6d93c6 (diff) | |
download | libtdevnc-515dbae42a295fc90bec4dc13f91338cb8135e70.tar.gz libtdevnc-515dbae42a295fc90bec4dc13f91338cb8135e70.zip |
x11vnc: improve scaled grid calc to regain text compression. add :pad option
-rw-r--r-- | x11vnc/ChangeLog | 5 | ||||
-rw-r--r-- | x11vnc/x11vnc.c | 109 |
2 files changed, 99 insertions, 15 deletions
diff --git a/x11vnc/ChangeLog b/x11vnc/ChangeLog index 74c770b..16ab8b0 100644 --- a/x11vnc/ChangeLog +++ b/x11vnc/ChangeLog @@ -1,3 +1,8 @@ +2004-07-01 Karl Runge <runge@karlrunge.com> + * improve scaled grid calculation to prevent drift (which causes + drift in pixel weights and poorer tightvnc compression) + * add ":pad" scale option, detect small fraction scale = m/n. + 2004-06-28 Karl Runge <runge@karlrunge.com> * round scaled width to multiple of 4 to make vncviewer happy. * allow override of above ":n4" and allow 4 point interpolation diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c index 57d004f..a9b0fa7 100644 --- a/x11vnc/x11vnc.c +++ b/x11vnc/x11vnc.c @@ -156,7 +156,7 @@ #endif /* date +'"lastmod: %Y-%m-%d";' */ -char lastmod[] = "lastmod: 2004-06-28"; +char lastmod[] = "lastmod: 2004-07-01"; /* X display info */ Display *dpy = 0; @@ -195,9 +195,11 @@ int rfb_bytes_per_line; int scaling = 0; int scaling_noblend = 0; int scaling_nomult4 = 0; +int scaling_pad = 0; int scaling_interpolate = 0; double scale_fac = 1.0; int scaled_x = 0, scaled_y = 0; +int scale_numer = 0, scale_denom = 0; /* size of the basic tile unit that is polled for changes: */ int tile_x = 32; @@ -3742,6 +3744,33 @@ void initialize_screen(int *argc, char **argv, XImage *fb) { double eps = 0.000001; width = (int) (width * scale_fac + eps); height = (int) (height * scale_fac + eps); + if (scale_denom && scaling_pad) { + /* it is not clear this padding is useful anymore */ + rfbLog("width %% denom: %d %% %d = %d\n", width, + scale_denom, width % scale_denom); + rfbLog("height %% denom: %d %% %d = %d\n", height, + scale_denom, height % scale_denom); + if (width % scale_denom != 0) { + int w = width; + w += scale_denom - (w % scale_denom); + if (!scaling_nomult4 && w % 4 != 0) { + /* need to make mult of 4 as well */ + int c = 0; + while (w % 4 != 0 && c++ <= 5) { + w += scale_denom; + } + } + width = w; + rfbLog("padded width to: %d (mult of %d%s\n", + width, scale_denom, !scaling_nomult4 ? + " and 4)" : ")"); + } + if (height % scale_denom != 0) { + height += scale_denom - (height % scale_denom); + rfbLog("padded height to: %d (mult of %d)\n", + height, scale_denom); + } + } if (!scaling_nomult4 && width % 4 != 0 && width > 2) { /* reset width to be multiple of 4 */ int width0 = width; @@ -3872,6 +3901,7 @@ void initialize_screen(int *argc, char **argv, XImage *fb) { main_fb = fb->data; if (scaling) { rfb_fb = (char *) malloc(rfb_bytes_per_line * height); + memset(rfb_fb, 0, rfb_bytes_per_line * height); } else { rfb_fb = main_fb; } @@ -4799,8 +4829,6 @@ weights for this scaled pixel are: * the loop over the 4 pixels. */ -#define FPTYPE double - static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) { /* * Notation: @@ -4816,21 +4844,21 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) { int i, j, i1, i2, j1, j2; /* indices for scaled fb (dest) */ int I, J, I1, I2, J1, J2; /* indices for main fb (source) */ - FPTYPE w, wx, wy, wtot; /* pixel weights */ + double w, wx, wy, wtot; /* pixel weights */ - FPTYPE x1, y1, x2, y2; /* x-y coords for destination pixels edges */ - FPTYPE dx, dy; /* size of destination pixel */ + double x1, y1, x2, y2; /* x-y coords for destination pixels edges */ + double dx, dy; /* size of destination pixel */ - FPTYPE ddx, ddy; /* for interpolation expansion */ + double ddx, ddy; /* for interpolation expansion */ char *src, *dest; /* pointers to the two framebuffers */ - FPTYPE pixave[4]; /* for averaging pixel values */ + double pixave[4]; /* for averaging pixel values */ unsigned short us; int shrink; /* whether shrinking or expanding */ - static int constant_weights = -1; + static int constant_weights = -1, cnt = 0; if (scale_fac <= 1.0) { shrink = 1; @@ -4865,8 +4893,24 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) { * both are > 1 (e.g. 1.333 for -scale 3/4) * they should also be equal but we don't assume it. */ - dx = (FPTYPE) Nx / nx; - dy = (FPTYPE) Ny / ny; + + /* + * This original way is probably incorrect, giving rise to dx and + * dy that will not exactly line up with the grid for 2/3, etc. + * This gives rise to a whole spectrum of weights, leading to poor + * tightvnc (and other encoding) compression. + */ +#if 0 + dx = (double) Nx / nx; + dy = (double) Ny / ny; +#endif + + /* + * This new way is probably the best we can do, take the inverse + * of the scaling factor to double precision. + */ + dx = 1.0/scale_fac; + dy = 1.0/scale_fac; /* * find the extent of the change the input rectangle induces in @@ -4895,7 +4939,7 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) { * let's special case these. * * If scale = 1/n and n divides Nx and Ny, the pixel weights - * are constant. + * are constant (e.g. 1/2 => equal on 2x2 square). */ if (constant_weights < 0) { int n = 0; @@ -4903,7 +4947,7 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) { for (i = 2; i<=128; i++) { double test = ((double) 1)/ i; - double diff, eps = 1.0e-9; + double diff, eps = 1.0e-7; diff = scale_fac - test; if (-eps < diff && diff < eps) { n = i; @@ -4930,6 +4974,10 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) { */ for (j=j1; j<j2; j++) { y1 = j * dy; /* top edge */ + if (y1 > Ny - 1) { + /* can go over with dy = 1/scale_fac */ + y1 = Ny - 1; + } y2 = y1 + dy; /* bottom edge */ /* Find main fb indices covered by this dest pixel: */ @@ -4949,8 +4997,14 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) { for (i=i1; i<i2; i++) { x1 = i * dx; /* left edge */ + if (x1 > Nx - 1) { + /* can go over with dx = 1/scale_fac */ + x1 = Nx - 1; + } x2 = x1 + dx; /* right edge */ + cnt++; + /* Find main fb indices covered by this dest pixel: */ I1 = (int) FLOOR(x1); if (I1 >= Nx) I1 = Nx - 1; @@ -5100,6 +5154,9 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) { } } + if (wtot <= 0.0) { + wtot = 1.0; + } wtot = 1.0/wtot; /* normalization factor */ /* place weighted average pixel in the scaled fb: */ @@ -7134,7 +7191,7 @@ int main(int argc, char* argv[]) { } else if (!strcmp(arg, "-scale")) { int m, n; char *p; - float f; + double f; i++; if ( (p = strchr(argv[i], ':')) != NULL) { /* options */ @@ -7147,15 +7204,35 @@ int main(int argc, char* argv[]) { if (strstr(p+1, "in") != NULL) { scaling_interpolate = 1; } + if (strstr(p+1, "pad") != NULL) { + scaling_pad = 1; + } *p = '\0'; } if (strchr(argv[i], '.') != NULL) { - if (sscanf(argv[i], "%f", &f) != 1) { + double test, diff, eps = 1.0e-7; + if (sscanf(argv[i], "%lf", &f) != 1) { fprintf(stderr, "bad -scale arg: %s\n", argv[i]); exit(1); } scale_fac = (double) f; + /* look for common fractions from small ints: */ + for (n=2; n<=10; n++) { + for (m=1; m<n; m++) { + test = ((double) m)/ n; + diff = scale_fac - test; + if (-eps < diff && diff < eps) { + scale_numer = m; + scale_denom = n; + break; + + } + } + if (scale_denom) { + break; + } + } } else { if (sscanf(argv[i], "%d/%d", &m, &n) != 2) { fprintf(stderr, "bad -scale arg: %s\n", @@ -7163,6 +7240,8 @@ int main(int argc, char* argv[]) { exit(1); } scale_fac = ((double) m)/ n; + scale_numer = m; + scale_denom = n; } if (scale_fac == 1.0) { fprintf(stderr, "scaling disabled for factor " |