Commit 515dbae4 authored by runge's avatar runge

x11vnc: improve scaled grid calc to regain text compression. add :pad option

parent b68e3879
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
......
......@@ -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 "
......
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