📄 translate.c
字号:
/* * translate.c - translate between different pixel formats *//* * 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"static void PrintPixelFormat(rfbPixelFormat *pf);static Bool rfbSetClientColourMapBGR233();Bool rfbEconomicTranslate = FALSE;/* * Structure representing pixel format for RFB server (i.e. us). */rfbPixelFormat rfbServerFormat;/* * Some standard pixel formats. */static const rfbPixelFormat BGR233Format = { 8, 8, 0, 1, 7, 7, 3, 0, 3, 6};/* * Macro to compare pixel formats. */#define PF_EQ(x,y) \ ((x.bitsPerPixel == y.bitsPerPixel) && \ (x.depth == y.depth) && \ ((x.bigEndian == y.bigEndian) || (x.bitsPerPixel == 8)) && \ (x.trueColour == y.trueColour) && \ (!x.trueColour || ((x.redMax == y.redMax) && \ (x.greenMax == y.greenMax) && \ (x.blueMax == y.blueMax) && \ (x.redShift == y.redShift) && \ (x.greenShift == y.greenShift) && \ (x.blueShift == y.blueShift))))#define CONCAT2(a,b) a##b#define CONCAT2E(a,b) CONCAT2(a,b)#define CONCAT4(a,b,c,d) a##b##c##d#define CONCAT4E(a,b,c,d) CONCAT4(a,b,c,d)#define OUT 8#include "tableinittctemplate.c"#include "tableinitcmtemplate.c"#define IN 8#include "tabletranstemplate.c"#undef IN#define IN 16#include "tabletranstemplate.c"#undef IN#define IN 32#include "tabletranstemplate.c"#undef IN#undef OUT#define OUT 16#include "tableinittctemplate.c"#include "tableinitcmtemplate.c"#define IN 8#include "tabletranstemplate.c"#undef IN#define IN 16#include "tabletranstemplate.c"#undef IN#define IN 32#include "tabletranstemplate.c"#undef IN#undef OUT#define OUT 32#include "tableinittctemplate.c"#include "tableinitcmtemplate.c"#define IN 8#include "tabletranstemplate.c"#undef IN#define IN 16#include "tabletranstemplate.c"#undef IN#define IN 32#include "tabletranstemplate.c"#undef IN#undef OUTtypedef void (*rfbInitTableFnType)(char **table, rfbPixelFormat *in, rfbPixelFormat *out);rfbInitTableFnType rfbInitTrueColourSingleTableFns[3] = { rfbInitTrueColourSingleTable8, rfbInitTrueColourSingleTable16, rfbInitTrueColourSingleTable32};rfbInitTableFnType rfbInitColourMapSingleTableFns[3] = { rfbInitColourMapSingleTable8, rfbInitColourMapSingleTable16, rfbInitColourMapSingleTable32};rfbInitTableFnType rfbInitTrueColourRGBTablesFns[3] = { rfbInitTrueColourRGBTables8, rfbInitTrueColourRGBTables16, rfbInitTrueColourRGBTables32};rfbTranslateFnType rfbTranslateWithSingleTableFns[3][3] = { { rfbTranslateWithSingleTable8to8, rfbTranslateWithSingleTable8to16, rfbTranslateWithSingleTable8to32 }, { rfbTranslateWithSingleTable16to8, rfbTranslateWithSingleTable16to16, rfbTranslateWithSingleTable16to32 }, { rfbTranslateWithSingleTable32to8, rfbTranslateWithSingleTable32to16, rfbTranslateWithSingleTable32to32 }};rfbTranslateFnType rfbTranslateWithRGBTablesFns[3][3] = { { rfbTranslateWithRGBTables8to8, rfbTranslateWithRGBTables8to16, rfbTranslateWithRGBTables8to32 }, { rfbTranslateWithRGBTables16to8, rfbTranslateWithRGBTables16to16, rfbTranslateWithRGBTables16to32 }, { rfbTranslateWithRGBTables32to8, rfbTranslateWithRGBTables32to16, rfbTranslateWithRGBTables32to32 }};/* * rfbTranslateNone is used when no translation is required. */voidrfbTranslateNone(char *table, rfbPixelFormat *in, rfbPixelFormat *out, char *iptr, char *optr, int bytesBetweenInputLines, int width, int height){ int bytesPerOutputLine = width * (out->bitsPerPixel / 8); while (height > 0) { memcpy(optr, iptr, bytesPerOutputLine); iptr += bytesBetweenInputLines; optr += bytesPerOutputLine; height--; }}/* * rfbSetTranslateFunction sets the translation function. */BoolrfbSetTranslateFunction(cl) rfbClientPtr cl;{ rfbLog("Pixel format for client %s:\n",cl->host); PrintPixelFormat(&cl->format); /* * Check that bits per pixel values are valid */ if ((rfbServerFormat.bitsPerPixel != 8) && (rfbServerFormat.bitsPerPixel != 16) && (rfbServerFormat.bitsPerPixel != 32)) { rfbLog("%s: server bits per pixel not 8, 16 or 32\n", "rfbSetTranslateFunction"); rfbCloseSock(cl->sock); return FALSE; } if ((cl->format.bitsPerPixel != 8) && (cl->format.bitsPerPixel != 16) && (cl->format.bitsPerPixel != 32)) { rfbLog("%s: client bits per pixel not 8, 16 or 32\n", "rfbSetTranslateFunction"); rfbCloseSock(cl->sock); return FALSE; } if (!rfbServerFormat.trueColour && (rfbServerFormat.bitsPerPixel != 8)) { rfbLog("rfbSetTranslateFunction: server has colour map " "but %d-bit - can only cope with 8-bit colour maps\n", rfbServerFormat.bitsPerPixel); rfbCloseSock(cl->sock); return FALSE; } if (!cl->format.trueColour && (cl->format.bitsPerPixel != 8)) { rfbLog("rfbSetTranslateFunction: client has colour map " "but %d-bit - can only cope with 8-bit colour maps\n", cl->format.bitsPerPixel); rfbCloseSock(cl->sock); return FALSE; } /* * bpp is valid, now work out how to translate */ if (!cl->format.trueColour) { /* ? -> colour map */ if (!rfbServerFormat.trueColour) { /* colour map -> colour map */ rfbLog("rfbSetTranslateFunction: both 8-bit colour map: " "no translation needed\n"); cl->translateFn = rfbTranslateNone; return rfbSetClientColourMap(cl, 0, 0); } /* * truecolour -> colour map * * Set client's colour map to BGR233, then effectively it's * truecolour as well */ if (!rfbSetClientColourMapBGR233(cl)) return FALSE; cl->format = BGR233Format; } /* ? -> truecolour */ if (!rfbServerFormat.trueColour) { /* colour map -> truecolour */ rfbLog("rfbSetTranslateFunction: client is %d-bit trueColour," " server has colour map\n",cl->format.bitsPerPixel); cl->translateFn = rfbTranslateWithSingleTableFns [rfbServerFormat.bitsPerPixel / 16] [cl->format.bitsPerPixel / 16]; return rfbSetClientColourMap(cl, 0, 0); } /* truecolour -> truecolour */ if (PF_EQ(cl->format,rfbServerFormat)) { /* client & server the same */ rfbLog(" no translation needed\n"); cl->translateFn = rfbTranslateNone; return TRUE; } if ((rfbServerFormat.bitsPerPixel < 16) || (!rfbEconomicTranslate && (rfbServerFormat.bitsPerPixel == 16))) { /* we can use a single lookup table for <= 16 bpp */ cl->translateFn = rfbTranslateWithSingleTableFns [rfbServerFormat.bitsPerPixel / 16] [cl->format.bitsPerPixel / 16]; (*rfbInitTrueColourSingleTableFns [cl->format.bitsPerPixel / 16]) (&cl->translateLookupTable, &rfbServerFormat, &cl->format); } else { /* otherwise we use three separate tables for red, green and blue */ cl->translateFn = rfbTranslateWithRGBTablesFns [rfbServerFormat.bitsPerPixel / 16] [cl->format.bitsPerPixel / 16]; (*rfbInitTrueColourRGBTablesFns [cl->format.bitsPerPixel / 16]) (&cl->translateLookupTable, &rfbServerFormat, &cl->format); } return TRUE;}/* * rfbSetClientColourMapBGR233 sets the client's colour map so that it's * just like an 8-bit BGR233 true colour client. */static BoolrfbSetClientColourMapBGR233(cl) rfbClientPtr cl;{ char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2]; rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf; CARD16 *rgb = (CARD16 *)(&buf[sz_rfbSetColourMapEntriesMsg]); int i, len; int r, g, b; if (cl->format.bitsPerPixel != 8) { rfbLog("%s: client not 8 bits per pixel\n", "rfbSetClientColourMapBGR233"); rfbCloseSock(cl->sock); return FALSE; } scme->type = rfbSetColourMapEntries; scme->firstColour = Swap16IfLE(0); scme->nColours = Swap16IfLE(256); len = sz_rfbSetColourMapEntriesMsg; i = 0; for (b = 0; b < 4; b++) { for (g = 0; g < 8; g++) { for (r = 0; r < 8; r++) { rgb[i++] = Swap16IfLE(r * 65535 / 7); rgb[i++] = Swap16IfLE(g * 65535 / 7); rgb[i++] = Swap16IfLE(b * 65535 / 3); } } } len += 256 * 3 * 2; if (WriteExact(cl->sock, buf, len) < 0) { rfbLogPerror("rfbSetClientColourMapBGR233: write"); rfbCloseSock(cl->sock); return FALSE; } return TRUE;}/* * rfbSetClientColourMap is called to set the client's colour map. If the * client is a true colour client, we simply update our own translation table * and mark the whole screen as having been modified. */BoolrfbSetClientColourMap(cl, firstColour, nColours) rfbClientPtr cl; int firstColour; int nColours;{ EntryPtr pent; int i, r, g, b; BoxRec box; if (nColours == 0) { nColours = rfbInstalledColormap->pVisual->ColormapEntries; } if (rfbServerFormat.trueColour || !cl->readyForSetColourMapEntries) { return TRUE; } if (cl->format.trueColour) { (*rfbInitColourMapSingleTableFns [cl->format.bitsPerPixel / 16]) (&cl->translateLookupTable, &rfbServerFormat, &cl->format); REGION_UNINIT(pScreen,&cl->modifiedRegion); box.x1 = box.y1 = 0; box.x2 = rfbScreen.width; box.y2 = rfbScreen.height; REGION_INIT(pScreen,&cl->modifiedRegion,&box,0); return TRUE; } return rfbSendSetColourMapEntries(cl, firstColour, nColours);}/* * rfbSetClientColourMaps sets the colour map for each RFB client. */voidrfbSetClientColourMaps(firstColour, nColours) int firstColour; int nColours;{ rfbClientPtr cl, nextCl; for (cl = rfbClientHead; cl; cl = nextCl) { nextCl = cl->next; rfbSetClientColourMap(cl, firstColour, nColours); }}static voidPrintPixelFormat(pf) rfbPixelFormat *pf;{ if (pf->bitsPerPixel == 1) { rfbLog(" 1 bpp, %s sig bit in each byte is leftmost on the screen.\n", (pf->bigEndian ? "most" : "least")); } else { rfbLog(" %d bpp, depth %d%s\n",pf->bitsPerPixel,pf->depth, ((pf->bitsPerPixel == 8) ? "" : (pf->bigEndian ? ", big endian" : ", little endian"))); if (pf->trueColour) { rfbLog(" true colour: max r %d g %d b %d, shift r %d g %d b %d\n", pf->redMax, pf->greenMax, pf->blueMax, pf->redShift, pf->greenShift, pf->blueShift); } else { rfbLog(" uses a colour map (not true colour).\n"); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -