📄 tight.c
字号:
CARD32 colorValue; int *w_ptr, *h_ptr;{ int dx, dy, dw, dh; int w_prev; int w_best = 0, h_best = 0; w_prev = w; for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) { dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ? MAX_SPLIT_TILE_SIZE : (y + h - dy); dw = (w_prev > MAX_SPLIT_TILE_SIZE) ? MAX_SPLIT_TILE_SIZE : w_prev; if (!CheckSolidTile(x, dy, dw, dh, &colorValue, TRUE)) break; for (dx = x + dw; dx < x + w_prev;) { dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w_prev) ? MAX_SPLIT_TILE_SIZE : (x + w_prev - dx); if (!CheckSolidTile(dx, dy, dw, dh, &colorValue, TRUE)) break; dx += dw; } w_prev = dx - x; if (w_prev * (dy + dh - y) > w_best * h_best) { w_best = w_prev; h_best = dy + dh - y; } } *w_ptr = w_best; *h_ptr = h_best;}static voidExtendSolidArea(x, y, w, h, colorValue, x_ptr, y_ptr, w_ptr, h_ptr) int x, y, w, h; CARD32 colorValue; int *x_ptr, *y_ptr, *w_ptr, *h_ptr;{ int cx, cy; /* Try to extend the area upwards. */ for ( cy = *y_ptr - 1; cy >= y && CheckSolidTile(*x_ptr, cy, *w_ptr, 1, &colorValue, TRUE); cy-- ); *h_ptr += *y_ptr - (cy + 1); *y_ptr = cy + 1; /* ... downwards. */ for ( cy = *y_ptr + *h_ptr; cy < y + h && CheckSolidTile(*x_ptr, cy, *w_ptr, 1, &colorValue, TRUE); cy++ ); *h_ptr += cy - (*y_ptr + *h_ptr); /* ... to the left. */ for ( cx = *x_ptr - 1; cx >= x && CheckSolidTile(cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE); cx-- ); *w_ptr += *x_ptr - (cx + 1); *x_ptr = cx + 1; /* ... to the right. */ for ( cx = *x_ptr + *w_ptr; cx < x + w && CheckSolidTile(cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE); cx++ ); *w_ptr += cx - (*x_ptr + *w_ptr);}/* * Check if a rectangle is all of the same color. If needSameColor is * set to non-zero, then also check that its color equals to the * *colorPtr value. The result is 1 if the test is successfull, and in * that case new color will be stored in *colorPtr. */static BoolCheckSolidTile(x, y, w, h, colorPtr, needSameColor) int x, y, w, h; CARD32 *colorPtr; Bool needSameColor;{ switch(rfbServerFormat.bitsPerPixel) { case 32: return CheckSolidTile32(x, y, w, h, colorPtr, needSameColor); case 16: return CheckSolidTile16(x, y, w, h, colorPtr, needSameColor); default: return CheckSolidTile8(x, y, w, h, colorPtr, needSameColor); }}#define DEFINE_CHECK_SOLID_FUNCTION(bpp) \ \static Bool \CheckSolidTile##bpp(x, y, w, h, colorPtr, needSameColor) \ int x, y; \ CARD32 *colorPtr; \ Bool needSameColor; \{ \ CARD##bpp *fbptr; \ CARD##bpp colorValue; \ int dx, dy; \ \ fbptr = (CARD##bpp *) \ &rfbScreen.pfbMemory[y * rfbScreen.paddedWidthInBytes + x * (bpp/8)]; \ \ colorValue = *fbptr; \ if (needSameColor && (CARD32)colorValue != *colorPtr) \ return FALSE; \ \ for (dy = 0; dy < h; dy++) { \ for (dx = 0; dx < w; dx++) { \ if (colorValue != fbptr[dx]) \ return FALSE; \ } \ fbptr = (CARD##bpp *)((CARD8 *)fbptr + rfbScreen.paddedWidthInBytes); \ } \ \ *colorPtr = (CARD32)colorValue; \ return TRUE; \}DEFINE_CHECK_SOLID_FUNCTION(8)DEFINE_CHECK_SOLID_FUNCTION(16)DEFINE_CHECK_SOLID_FUNCTION(32)static BoolSendRectSimple(cl, x, y, w, h) rfbClientPtr cl; int x, y, w, h;{ int maxBeforeSize, maxAfterSize; int maxRectSize, maxRectWidth; int subrectMaxWidth, subrectMaxHeight; int dx, dy; int rw, rh; maxRectSize = tightConf[compressLevel].maxRectSize; maxRectWidth = tightConf[compressLevel].maxRectWidth; maxBeforeSize = maxRectSize * (cl->format.bitsPerPixel / 8); maxAfterSize = maxBeforeSize + (maxBeforeSize + 99) / 100 + 12; if (tightBeforeBufSize < maxBeforeSize) { tightBeforeBufSize = maxBeforeSize; if (tightBeforeBuf == NULL) tightBeforeBuf = (char *)xalloc(tightBeforeBufSize); else tightBeforeBuf = (char *)xrealloc(tightBeforeBuf, tightBeforeBufSize); } if (tightAfterBufSize < maxAfterSize) { tightAfterBufSize = maxAfterSize; if (tightAfterBuf == NULL) tightAfterBuf = (char *)xalloc(tightAfterBufSize); else tightAfterBuf = (char *)xrealloc(tightAfterBuf, tightAfterBufSize); } if (w > maxRectWidth || w * h > maxRectSize) { subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; subrectMaxHeight = maxRectSize / subrectMaxWidth; for (dy = 0; dy < h; dy += subrectMaxHeight) { for (dx = 0; dx < w; dx += maxRectWidth) { rw = (dx + maxRectWidth < w) ? maxRectWidth : w - dx; rh = (dy + subrectMaxHeight < h) ? subrectMaxHeight : h - dy; if (!SendSubrect(cl, x+dx, y+dy, rw, rh)) return FALSE; } } } else { if (!SendSubrect(cl, x, y, w, h)) return FALSE; } return TRUE;}static BoolSendSubrect(cl, x, y, w, h) rfbClientPtr cl; int x, y, w, h;{ char *fbptr; Bool success = FALSE; /* Send pending data if there is more than 128 bytes. */ if (ublen > 128) { if (!rfbSendUpdateBuf(cl)) return FALSE; } if (!SendTightHeader(cl, x, y, w, h)) return FALSE; fbptr = (rfbScreen.pfbMemory + (rfbScreen.paddedWidthInBytes * y) + (x * (rfbScreen.bitsPerPixel / 8))); (*cl->translateFn)(cl->translateLookupTable, &rfbServerFormat, &cl->format, fbptr, tightBeforeBuf, rfbScreen.paddedWidthInBytes, w, h); paletteMaxColors = w * h / tightConf[compressLevel].idxMaxColorsDivisor; if ( paletteMaxColors < 2 && w * h >= tightConf[compressLevel].monoMinRectSize ) { paletteMaxColors = 2; } switch (cl->format.bitsPerPixel) { case 8: FillPalette8(w * h); break; case 16: FillPalette16(w * h); break; default: FillPalette32(w * h); } switch (paletteNumColors) { case 0: /* Truecolor image */ if (DetectSmoothImage(&cl->format, w, h)) { if (qualityLevel != -1) { success = SendJpegRect(cl, x, y, w, h, tightConf[qualityLevel].jpegQuality); } else { success = SendGradientRect(cl, w, h); } } else { success = SendFullColorRect(cl, w, h); } break; case 1: /* Solid rectangle */ success = SendSolidRect(cl); break; case 2: /* Two-color rectangle */ success = SendMonoRect(cl, w, h); break; default: /* Up to 256 different colors */ if ( paletteNumColors > 96 && qualityLevel != -1 && qualityLevel <= 3 && DetectSmoothImage(&cl->format, w, h) ) { success = SendJpegRect(cl, x, y, w, h, tightConf[qualityLevel].jpegQuality); } else { success = SendIndexedRect(cl, w, h); } } return success;}static BoolSendTightHeader(cl, x, y, w, h) rfbClientPtr cl; int x, y, w, h;{ rfbFramebufferUpdateRectHeader rect; if (ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { if (!rfbSendUpdateBuf(cl)) return FALSE; } rect.r.x = Swap16IfLE(x); rect.r.y = Swap16IfLE(y); rect.r.w = Swap16IfLE(w); rect.r.h = Swap16IfLE(h); rect.encoding = Swap32IfLE(rfbEncodingTight); memcpy(&updateBuf[ublen], (char *)&rect, sz_rfbFramebufferUpdateRectHeader); ublen += sz_rfbFramebufferUpdateRectHeader; cl->rfbRectanglesSent[rfbEncodingTight]++; cl->rfbBytesSent[rfbEncodingTight] += sz_rfbFramebufferUpdateRectHeader; return TRUE;}/* * Subencoding implementations. */static BoolSendSolidRect(cl) rfbClientPtr cl;{ int len; if (usePixelFormat24) { Pack24(tightBeforeBuf, &cl->format, 1); len = 3; } else len = cl->format.bitsPerPixel / 8; if (ublen + 1 + len > UPDATE_BUF_SIZE) { if (!rfbSendUpdateBuf(cl)) return FALSE; } updateBuf[ublen++] = (char)(rfbTightFill << 4); memcpy (&updateBuf[ublen], tightBeforeBuf, len); ublen += len; cl->rfbBytesSent[rfbEncodingTight] += len + 1; return TRUE;}static BoolSendMonoRect(cl, w, h) rfbClientPtr cl; int w, h;{ int streamId = 1; int paletteLen, dataLen; if ( (ublen + TIGHT_MIN_TO_COMPRESS + 6 + 2 * cl->format.bitsPerPixel / 8) > UPDATE_BUF_SIZE ) { if (!rfbSendUpdateBuf(cl)) return FALSE; } /* Prepare tight encoding header. */ dataLen = (w + 7) / 8; dataLen *= h; updateBuf[ublen++] = (streamId | rfbTightExplicitFilter) << 4; updateBuf[ublen++] = rfbTightFilterPalette; updateBuf[ublen++] = 1; /* Prepare palette, convert image. */ switch (cl->format.bitsPerPixel) { case 32:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -