summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrunge <runge>2004-07-02 01:35:59 +0000
committerrunge <runge>2004-07-02 01:35:59 +0000
commit515dbae42a295fc90bec4dc13f91338cb8135e70 (patch)
tree9fba0a6f6abf8c2eaf71c8e8755d9219293f2045
parentb68e3879493c12777ad375742e6871acae6d93c6 (diff)
downloadlibtdevnc-515dbae4.tar.gz
libtdevnc-515dbae4.zip
x11vnc: improve scaled grid calc to regain text compression. add :pad option
-rw-r--r--x11vnc/ChangeLog5
-rw-r--r--x11vnc/x11vnc.c109
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 "