📄 tight.c
字号:
pixHere[c] = (int)(pix >> shiftBits[c] & maxColor[c]); \ *prevRowPtr++ = pixHere[c]; \ \ prediction = pixLeft[c] + pixUpper[c] - pixUpperLeft[c]; \ if (prediction < 0) { \ prediction = 0; \ } else if (prediction > maxColor[c]) { \ prediction = maxColor[c]; \ } \ diff |= ((pixHere[c] - prediction) & maxColor[c]) \ << shiftBits[c]; \ } \ if (endianMismatch) { \ diff = Swap##bpp(diff); \ } \ *buf++ = diff; \ } \ } \}DEFINE_GRADIENT_FILTER_FUNCTION(16)DEFINE_GRADIENT_FILTER_FUNCTION(32)/* * Code to guess if given rectangle is suitable for smooth image * compression (by applying "gradient" filter or JPEG coder). */#define JPEG_MIN_RECT_SIZE 4096#define DETECT_SUBROW_WIDTH 7#define DETECT_MIN_WIDTH 8#define DETECT_MIN_HEIGHT 8static intDetectSmoothImage (fmt, w, h) rfbPixelFormat *fmt; int w, h;{ unsigned long avgError; if ( rfbServerFormat.bitsPerPixel == 8 || fmt->bitsPerPixel == 8 || w < DETECT_MIN_WIDTH || h < DETECT_MIN_HEIGHT ) { return 0; } if (qualityLevel != -1) { if (w * h < JPEG_MIN_RECT_SIZE) { return 0; } } else { if ( rfbTightDisableGradient || w * h < tightConf[compressLevel].gradientMinRectSize ) { return 0; } } if (fmt->bitsPerPixel == 32) { if (usePixelFormat24) { avgError = DetectSmoothImage24(fmt, w, h); if (qualityLevel != -1) { return (avgError < tightConf[qualityLevel].jpegThreshold24); } return (avgError < tightConf[compressLevel].gradientThreshold24); } else { avgError = DetectSmoothImage32(fmt, w, h); } } else { avgError = DetectSmoothImage16(fmt, w, h); } if (qualityLevel != -1) { return (avgError < tightConf[qualityLevel].jpegThreshold); } return (avgError < tightConf[compressLevel].gradientThreshold);}static unsigned longDetectSmoothImage24 (fmt, w, h) rfbPixelFormat *fmt; int w, h;{ int off; int x, y, d, dx, c; int diffStat[256]; int pixelCount = 0; int pix, left[3]; unsigned long avgError; /* If client is big-endian, color samples begin from the second byte (offset 1) of a 32-bit pixel value. */ off = (fmt->bigEndian != 0); memset(diffStat, 0, 256*sizeof(int)); y = 0, x = 0; while (y < h && x < w) { for (d = 0; d < h - y && d < w - x - DETECT_SUBROW_WIDTH; d++) { for (c = 0; c < 3; c++) { left[c] = (int)tightBeforeBuf[((y+d)*w+x+d)*4+off+c] & 0xFF; } for (dx = 1; dx <= DETECT_SUBROW_WIDTH; dx++) { for (c = 0; c < 3; c++) { pix = (int)tightBeforeBuf[((y+d)*w+x+d+dx)*4+off+c] & 0xFF; diffStat[abs(pix - left[c])]++; left[c] = pix; } pixelCount++; } } if (w > h) { x += h; y = 0; } else { x = 0; y += w; } } if (diffStat[0] * 33 / pixelCount >= 95) return 0; avgError = 0; for (c = 1; c < 8; c++) { avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); if (diffStat[c] == 0 || diffStat[c] > diffStat[c-1] * 2) return 0; } for (; c < 256; c++) { avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); } avgError /= (pixelCount * 3 - diffStat[0]); return avgError;}#define DEFINE_DETECT_FUNCTION(bpp) \ \static unsigned long \DetectSmoothImage##bpp (fmt, w, h) \ rfbPixelFormat *fmt; \ int w, h; \{ \ Bool endianMismatch; \ CARD##bpp pix; \ int maxColor[3], shiftBits[3]; \ int x, y, d, dx, c; \ int diffStat[256]; \ int pixelCount = 0; \ int sample, sum, left[3]; \ unsigned long avgError; \ \ endianMismatch = (!rfbServerFormat.bigEndian != !fmt->bigEndian); \ \ maxColor[0] = fmt->redMax; \ maxColor[1] = fmt->greenMax; \ maxColor[2] = fmt->blueMax; \ shiftBits[0] = fmt->redShift; \ shiftBits[1] = fmt->greenShift; \ shiftBits[2] = fmt->blueShift; \ \ memset(diffStat, 0, 256*sizeof(int)); \ \ y = 0, x = 0; \ while (y < h && x < w) { \ for (d = 0; d < h - y && d < w - x - DETECT_SUBROW_WIDTH; d++) { \ pix = ((CARD##bpp *)tightBeforeBuf)[(y+d)*w+x+d]; \ if (endianMismatch) { \ pix = Swap##bpp(pix); \ } \ for (c = 0; c < 3; c++) { \ left[c] = (int)(pix >> shiftBits[c] & maxColor[c]); \ } \ for (dx = 1; dx <= DETECT_SUBROW_WIDTH; dx++) { \ pix = ((CARD##bpp *)tightBeforeBuf)[(y+d)*w+x+d+dx]; \ if (endianMismatch) { \ pix = Swap##bpp(pix); \ } \ sum = 0; \ for (c = 0; c < 3; c++) { \ sample = (int)(pix >> shiftBits[c] & maxColor[c]); \ sum += abs(sample - left[c]); \ left[c] = sample; \ } \ if (sum > 255) \ sum = 255; \ diffStat[sum]++; \ pixelCount++; \ } \ } \ if (w > h) { \ x += h; \ y = 0; \ } else { \ x = 0; \ y += w; \ } \ } \ \ if ((diffStat[0] + diffStat[1]) * 100 / pixelCount >= 90) \ return 0; \ \ avgError = 0; \ for (c = 1; c < 8; c++) { \ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); \ if (diffStat[c] == 0 || diffStat[c] > diffStat[c-1] * 2) \ return 0; \ } \ for (; c < 256; c++) { \ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); \ } \ avgError /= (pixelCount - diffStat[0]); \ \ return avgError; \}DEFINE_DETECT_FUNCTION(16)DEFINE_DETECT_FUNCTION(32)/* * JPEG compression stuff. */static struct jpeg_destination_mgr jpegDstManager;static Bool jpegError;static int jpegDstDataLen;static BoolSendJpegRect(cl, x, y, w, h, quality) rfbClientPtr cl; int x, y, w, h; int quality;{ struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; CARD8 *srcBuf; JSAMPROW rowPointer[1]; int dy; if (rfbServerFormat.bitsPerPixel == 8) return SendFullColorRect(cl, w, h); srcBuf = (CARD8 *)xalloc(w * 3); if (srcBuf == NULL) { return SendFullColorRect(cl, w, h); } rowPointer[0] = srcBuf; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); cinfo.image_width = w; cinfo.image_height = h; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); JpegSetDstManager (&cinfo); jpeg_start_compress(&cinfo, TRUE); for (dy = 0; dy < h; dy++) { PrepareRowForJpeg(srcBuf, x, y + dy, w); jpeg_write_scanlines(&cinfo, rowPointer, 1); if (jpegError) break; } if (!jpegError) jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); xfree((char *)srcBuf); if (jpegError) return SendFullColorRect(cl, w, h); if (ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) { if (!rfbSendUpdateBuf(cl)) return FALSE; } updateBuf[ublen++] = (char)(rfbTightJpeg << 4); cl->rfbBytesSent[rfbEncodingTight]++; return SendCompressedData(cl, jpegDstDataLen);}static voidPrepareRowForJpeg(dst, x, y, count) CARD8 *dst; int x, y, count;{ if (rfbServerFormat.bitsPerPixel == 32) { if ( rfbServerFormat.redMax == 0xFF && rfbServerFormat.greenMax == 0xFF && rfbServerFormat.blueMax == 0xFF ) { PrepareRowForJpeg24(dst, x, y, count); } else { PrepareRowForJpeg32(dst, x, y, count); } } else { /* 16 bpp assumed. */ PrepareRowForJpeg16(dst, x, y, count); }}static voidPrepareRowForJpeg24(dst, x, y, count) CARD8 *dst; int x, y, count;{ CARD32 *fbptr; CARD32 pix; fbptr = (CARD32 *) &rfbScreen.pfbMemory[y * rfbScreen.paddedWidthInBytes + x * 4]; while (count--) { pix = *fbptr++; *dst++ = (CARD8)(pix >> rfbServerFormat.redShift); *dst++ = (CARD8)(pix >> rfbServerFormat.greenShift); *dst++ = (CARD8)(pix >> rfbServerFormat.blueShift); }}#define DEFINE_JPEG_GET_ROW_FUNCTION(bpp) \ \static void \PrepareRowForJpeg##bpp(dst, x, y, count) \ CARD8 *dst; \ int x, y, count; \{ \ CARD##bpp *fbptr; \ CARD##bpp pix; \ int inRed, inGreen, inBlue; \ \ fbptr = (CARD##bpp *) \ &rfbScreen.pfbMemory[y * rfbScreen.paddedWidthInBytes + \ x * (bpp / 8)]; \ \ while (count--) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -