📄 tight.c
字号:
/* * tight.c * * Routines to implement Tight Encoding *//* * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */#include <stdio.h>#include "rfb.h"#include <jpeglib.h>/* Note: The following constant should not be changed. */#define TIGHT_MIN_TO_COMPRESS 12/* The parameters below may be adjusted. */#define MIN_SPLIT_RECT_SIZE 4096#define MIN_SOLID_SUBRECT_SIZE 2048#define MAX_SPLIT_TILE_SIZE 16/* May be set to TRUE with "-lazytight" Xvnc option. */Bool rfbTightDisableGradient = FALSE;/* This variable is set on every rfbSendRectEncodingTight() call. */static Bool usePixelFormat24;/* Compression level stuff. The following array contains various encoder parameters for each of 10 compression levels (0..9). Last three parameters correspond to JPEG quality levels (0..9). */typedef struct TIGHT_CONF_s { int maxRectSize, maxRectWidth; int monoMinRectSize, gradientMinRectSize; int idxZlibLevel, monoZlibLevel, rawZlibLevel, gradientZlibLevel; int gradientThreshold, gradientThreshold24; int idxMaxColorsDivisor; int jpegQuality, jpegThreshold, jpegThreshold24;} TIGHT_CONF;static TIGHT_CONF tightConf[10] = { { 512, 32, 6, 65536, 0, 0, 0, 0, 0, 0, 4, 5, 10000, 23000 }, { 2048, 128, 6, 65536, 1, 1, 1, 0, 0, 0, 8, 10, 8000, 18000 }, { 6144, 256, 8, 65536, 3, 3, 2, 0, 0, 0, 24, 15, 6500, 15000 }, { 10240, 1024, 12, 65536, 5, 5, 3, 0, 0, 0, 32, 25, 5000, 12000 }, { 16384, 2048, 12, 65536, 6, 6, 4, 0, 0, 0, 32, 37, 4000, 10000 }, { 32768, 2048, 12, 4096, 7, 7, 5, 4, 150, 380, 32, 50, 3000, 8000 }, { 65536, 2048, 16, 4096, 7, 7, 6, 4, 170, 420, 48, 60, 2000, 5000 }, { 65536, 2048, 16, 4096, 8, 8, 7, 5, 180, 450, 64, 70, 1000, 2500 }, { 65536, 2048, 32, 8192, 9, 9, 8, 6, 190, 475, 64, 75, 500, 1200 }, { 65536, 2048, 32, 8192, 9, 9, 9, 6, 200, 500, 96, 80, 200, 500 }};static int compressLevel;static int qualityLevel;/* Stuff dealing with palettes. */typedef struct COLOR_LIST_s { struct COLOR_LIST_s *next; int idx; CARD32 rgb;} COLOR_LIST;typedef struct PALETTE_ENTRY_s { COLOR_LIST *listNode; int numPixels;} PALETTE_ENTRY;typedef struct PALETTE_s { PALETTE_ENTRY entry[256]; COLOR_LIST *hash[256]; COLOR_LIST list[256];} PALETTE;static int paletteNumColors, paletteMaxColors;static CARD32 monoBackground, monoForeground;static PALETTE palette;/* Pointers to dynamically-allocated buffers. */static int tightBeforeBufSize = 0;static char *tightBeforeBuf = NULL;static int tightAfterBufSize = 0;static char *tightAfterBuf = NULL;static int *prevRowBuf = NULL;/* Prototypes for static functions. */static void FindBestSolidArea (int x, int y, int w, int h, CARD32 colorValue, int *w_ptr, int *h_ptr);static void ExtendSolidArea (int x, int y, int w, int h, CARD32 colorValue, int *x_ptr, int *y_ptr, int *w_ptr, int *h_ptr);static Bool CheckSolidTile (int x, int y, int w, int h, CARD32 *colorPtr, Bool needSameColor);static Bool CheckSolidTile8 (int x, int y, int w, int h, CARD32 *colorPtr, Bool needSameColor);static Bool CheckSolidTile16 (int x, int y, int w, int h, CARD32 *colorPtr, Bool needSameColor);static Bool CheckSolidTile32 (int x, int y, int w, int h, CARD32 *colorPtr, Bool needSameColor);static Bool SendRectSimple (rfbClientPtr cl, int x, int y, int w, int h);static Bool SendSubrect (rfbClientPtr cl, int x, int y, int w, int h);static Bool SendTightHeader (rfbClientPtr cl, int x, int y, int w, int h);static Bool SendSolidRect (rfbClientPtr cl);static Bool SendMonoRect (rfbClientPtr cl, int w, int h);static Bool SendIndexedRect (rfbClientPtr cl, int w, int h);static Bool SendFullColorRect (rfbClientPtr cl, int w, int h);static Bool SendGradientRect (rfbClientPtr cl, int w, int h);static Bool CompressData(rfbClientPtr cl, int streamId, int dataLen, int zlibLevel, int zlibStrategy);static Bool SendCompressedData(rfbClientPtr cl, int compressedLen);static void FillPalette8(int count);static void FillPalette16(int count);static void FillPalette32(int count);static void PaletteReset(void);static int PaletteInsert(CARD32 rgb, int numPixels, int bpp);static void Pack24(char *buf, rfbPixelFormat *fmt, int count);static void EncodeIndexedRect16(CARD8 *buf, int count);static void EncodeIndexedRect32(CARD8 *buf, int count);static void EncodeMonoRect8(CARD8 *buf, int w, int h);static void EncodeMonoRect16(CARD8 *buf, int w, int h);static void EncodeMonoRect32(CARD8 *buf, int w, int h);static void FilterGradient24(char *buf, rfbPixelFormat *fmt, int w, int h);static void FilterGradient16(CARD16 *buf, rfbPixelFormat *fmt, int w, int h);static void FilterGradient32(CARD32 *buf, rfbPixelFormat *fmt, int w, int h);static int DetectSmoothImage(rfbPixelFormat *fmt, int w, int h);static unsigned long DetectSmoothImage24(rfbPixelFormat *fmt, int w, int h);static unsigned long DetectSmoothImage16(rfbPixelFormat *fmt, int w, int h);static unsigned long DetectSmoothImage32(rfbPixelFormat *fmt, int w, int h);static Bool SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, int quality);static void PrepareRowForJpeg(CARD8 *dst, int x, int y, int count);static void PrepareRowForJpeg24(CARD8 *dst, int x, int y, int count);static void PrepareRowForJpeg16(CARD8 *dst, int x, int y, int count);static void PrepareRowForJpeg32(CARD8 *dst, int x, int y, int count);static void JpegInitDestination(j_compress_ptr cinfo);static boolean JpegEmptyOutputBuffer(j_compress_ptr cinfo);static void JpegTermDestination(j_compress_ptr cinfo);static void JpegSetDstManager(j_compress_ptr cinfo);/* * Tight encoding implementation. */intrfbNumCodedRectsTight(cl, x, y, w, h) rfbClientPtr cl; int x, y, w, h;{ int maxRectSize, maxRectWidth; int subrectMaxWidth, subrectMaxHeight; /* No matter how many rectangles we will send if LastRect markers are used to terminate rectangle stream. */ if (cl->enableLastRectEncoding && w * h >= MIN_SPLIT_RECT_SIZE) return 0; maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize; maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth; if (w > maxRectWidth || w * h > maxRectSize) { subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; subrectMaxHeight = maxRectSize / subrectMaxWidth; return (((w - 1) / maxRectWidth + 1) * ((h - 1) / subrectMaxHeight + 1)); } else { return 1; }}BoolrfbSendRectEncodingTight(cl, x, y, w, h) rfbClientPtr cl; int x, y, w, h;{ int nMaxRows; CARD32 colorValue; int dx, dy, dw, dh; int x_best, y_best, w_best, h_best; char *fbptr; compressLevel = cl->tightCompressLevel; qualityLevel = cl->tightQualityLevel; if ( cl->format.depth == 24 && cl->format.redMax == 0xFF && cl->format.greenMax == 0xFF && cl->format.blueMax == 0xFF ) { usePixelFormat24 = TRUE; } else { usePixelFormat24 = FALSE; } if (!cl->enableLastRectEncoding || w * h < MIN_SPLIT_RECT_SIZE) return SendRectSimple(cl, x, y, w, h); /* Make sure we can write at least one pixel into tightBeforeBuf. */ if (tightBeforeBufSize < 4) { tightBeforeBufSize = 4; if (tightBeforeBuf == NULL) tightBeforeBuf = (char *)xalloc(tightBeforeBufSize); else tightBeforeBuf = (char *)xrealloc(tightBeforeBuf, tightBeforeBufSize); } /* Calculate maximum number of rows in one non-solid rectangle. */ { int maxRectSize, maxRectWidth, nMaxWidth; maxRectSize = tightConf[compressLevel].maxRectSize; maxRectWidth = tightConf[compressLevel].maxRectWidth; nMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; nMaxRows = maxRectSize / nMaxWidth; } /* Try to find large solid-color areas and send them separately. */ for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) { /* If a rectangle becomes too large, send its upper part now. */ if (dy - y >= nMaxRows) { if (!SendRectSimple(cl, x, y, w, nMaxRows)) return 0; y += nMaxRows; h -= nMaxRows; } dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ? MAX_SPLIT_TILE_SIZE : (y + h - dy); for (dx = x; dx < x + w; dx += MAX_SPLIT_TILE_SIZE) { dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w) ? MAX_SPLIT_TILE_SIZE : (x + w - dx); if (CheckSolidTile(dx, dy, dw, dh, &colorValue, FALSE)) { /* Get dimensions of solid-color area. */ FindBestSolidArea(dx, dy, w - (dx - x), h - (dy - y), colorValue, &w_best, &h_best); /* Make sure a solid rectangle is large enough (or the whole rectangle is of the same color). */ if ( w_best * h_best != w * h && w_best * h_best < MIN_SOLID_SUBRECT_SIZE ) continue; /* Try to extend solid rectangle to maximum size. */ x_best = dx; y_best = dy; ExtendSolidArea(x, y, w, h, colorValue, &x_best, &y_best, &w_best, &h_best); /* Send rectangles at top and left to solid-color area. */ if ( y_best != y && !SendRectSimple(cl, x, y, w, y_best-y) ) return FALSE; if ( x_best != x && !rfbSendRectEncodingTight(cl, x, y_best, x_best-x, h_best) ) return FALSE; /* Send solid-color rectangle. */ if (!SendTightHeader(cl, x_best, y_best, w_best, h_best)) return FALSE; fbptr = (rfbScreen.pfbMemory + (rfbScreen.paddedWidthInBytes * y_best) + (x_best * (rfbScreen.bitsPerPixel / 8))); (*cl->translateFn)(cl->translateLookupTable, &rfbServerFormat, &cl->format, fbptr, tightBeforeBuf, rfbScreen.paddedWidthInBytes, 1, 1); if (!SendSolidRect(cl)) return FALSE; /* Send remaining rectangles (at right and bottom). */ if ( x_best + w_best != x + w && !rfbSendRectEncodingTight(cl, x_best+w_best, y_best, w-(x_best-x)-w_best, h_best) ) return FALSE; if ( y_best + h_best != y + h && !rfbSendRectEncodingTight(cl, x, y_best+h_best, w, h-(y_best-y)-h_best) ) return FALSE; /* Return after all recursive calls are done. */ return TRUE; } } } /* No suitable solid-color rectangles found. */ return SendRectSimple(cl, x, y, w, h);}static voidFindBestSolidArea(x, y, w, h, colorValue, w_ptr, h_ptr) int x, y, w, h;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -