mirror of
https://github.com/TigerVNC/tigervnc.git
synced 2024-08-21 17:54:34 +02:00
![Constantin Kaplinsky](/assets/img/avatar_default.png)
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@2 3789f03b-4d11-0410-bbf8-ca57d06f2519
255 lines
8.1 KiB
C++
255 lines
8.1 KiB
C++
/* Copyright (C) 2002-2003 RealVNC Ltd. 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.
|
|
*/
|
|
//
|
|
// transInitTempl.h - templates for functions to initialise lookup tables for
|
|
// the translation functions.
|
|
//
|
|
// This file is #included after having set the following macros:
|
|
// BPPOUT - 8, 16 or 32
|
|
|
|
#if !defined(BPPOUT)
|
|
#error "transInitTempl.h: BPPOUT not defined"
|
|
#endif
|
|
|
|
namespace rfb {
|
|
|
|
// CONCAT2E concatenates its arguments, expanding them if they are macros
|
|
|
|
#ifndef CONCAT2E
|
|
#define CONCAT2(a,b) a##b
|
|
#define CONCAT2E(a,b) CONCAT2(a,b)
|
|
#endif
|
|
|
|
#ifndef SWAP16
|
|
#define SWAP16(n) ((((n) & 0xff) << 8) | (((n) >> 8) & 0xff))
|
|
#endif
|
|
|
|
#ifndef SWAP32
|
|
#define SWAP32(n) (((n) >> 24) | (((n) & 0x00ff0000) >> 8) | \
|
|
(((n) & 0x0000ff00) << 8) | ((n) << 24))
|
|
#endif
|
|
|
|
#define OUTPIXEL rdr::CONCAT2E(U,BPPOUT)
|
|
#define SWAPOUT CONCAT2E(SWAP,BPPOUT)
|
|
#define initSimpleCMtoTCOUT CONCAT2E(initSimpleCMtoTC,BPPOUT)
|
|
#define initSimpleTCtoTCOUT CONCAT2E(initSimpleTCtoTC,BPPOUT)
|
|
#define initSimpleCMtoCubeOUT CONCAT2E(initSimpleCMtoCube,BPPOUT)
|
|
#define initSimpleTCtoCubeOUT CONCAT2E(initSimpleTCtoCube,BPPOUT)
|
|
#define initRGBTCtoTCOUT CONCAT2E(initRGBTCtoTC,BPPOUT)
|
|
#define initRGBTCtoCubeOUT CONCAT2E(initRGBTCtoCube,BPPOUT)
|
|
#define initOneRGBTableOUT CONCAT2E(initOneRGBTable,BPPOUT)
|
|
#define initOneRGBCubeTableOUT CONCAT2E(initOneRGBCubeTable,BPPOUT)
|
|
|
|
#ifndef TRANS_INIT_TEMPL_ENDIAN_TEST
|
|
#define TRANS_INIT_TEMPL_ENDIAN_TEST
|
|
static rdr::U32 endianTest = 1;
|
|
static bool nativeBigEndian = *(rdr::U8*)(&endianTest) != 1;
|
|
#endif
|
|
|
|
void initSimpleCMtoTCOUT (rdr::U8** tablep, const PixelFormat& inPF,
|
|
ColourMap* cm, const PixelFormat& outPF)
|
|
{
|
|
if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian)
|
|
throw Exception("Internal error: inPF is not native endian");
|
|
|
|
int size = 1 << inPF.bpp;
|
|
|
|
delete [] *tablep;
|
|
*tablep = new rdr::U8[size * sizeof(OUTPIXEL)];
|
|
OUTPIXEL* table = (OUTPIXEL*)*tablep;
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
int r,g,b;
|
|
cm->lookup(i,&r,&g,&b);
|
|
|
|
table[i] = ((((r * outPF.redMax + 32767) / 65535) << outPF.redShift) |
|
|
(((g * outPF.greenMax + 32767) / 65535) << outPF.greenShift) |
|
|
(((b * outPF.blueMax + 32767) / 65535) << outPF.blueShift));
|
|
#if (BPPOUT != 8)
|
|
if (outPF.bigEndian != nativeBigEndian)
|
|
table[i] = SWAPOUT (table[i]);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void initSimpleTCtoTCOUT (rdr::U8** tablep, const PixelFormat& inPF,
|
|
const PixelFormat& outPF)
|
|
{
|
|
if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian)
|
|
throw Exception("Internal error: inPF is not native endian");
|
|
|
|
int size = 1 << inPF.bpp;
|
|
|
|
delete [] *tablep;
|
|
*tablep = new rdr::U8[size * sizeof(OUTPIXEL)];
|
|
OUTPIXEL* table = (OUTPIXEL*)*tablep;
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
int r = (i >> inPF.redShift) & inPF.redMax;
|
|
int g = (i >> inPF.greenShift) & inPF.greenMax;
|
|
int b = (i >> inPF.blueShift) & inPF.blueMax;
|
|
|
|
r = (r * outPF.redMax + inPF.redMax/2) / inPF.redMax;
|
|
g = (g * outPF.greenMax + inPF.greenMax/2) / inPF.greenMax;
|
|
b = (b * outPF.blueMax + inPF.blueMax/2) / inPF.blueMax;
|
|
|
|
table[i] = ((r << outPF.redShift) |
|
|
(g << outPF.greenShift) |
|
|
(b << outPF.blueShift));
|
|
#if (BPPOUT != 8)
|
|
if (outPF.bigEndian != nativeBigEndian)
|
|
table[i] = SWAPOUT (table[i]);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void initSimpleCMtoCubeOUT (rdr::U8** tablep, const PixelFormat& inPF,
|
|
ColourMap* cm, ColourCube* cube)
|
|
{
|
|
if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian)
|
|
throw Exception("Internal error: inPF is not native endian");
|
|
|
|
int size = 1 << inPF.bpp;
|
|
|
|
delete [] *tablep;
|
|
*tablep = new rdr::U8[size * sizeof(OUTPIXEL)];
|
|
OUTPIXEL* table = (OUTPIXEL*)*tablep;
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
int r,g,b;
|
|
cm->lookup(i,&r,&g,&b);
|
|
r = (r * (cube->nRed-1) + 32767) / 65535;
|
|
g = (g * (cube->nGreen-1) + 32767) / 65535;
|
|
b = (b * (cube->nBlue-1) + 32767) / 65535;
|
|
table[i] = cube->lookup(r, g, b);
|
|
}
|
|
}
|
|
|
|
void initSimpleTCtoCubeOUT (rdr::U8** tablep, const PixelFormat& inPF,
|
|
ColourCube* cube)
|
|
{
|
|
if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian)
|
|
throw Exception("Internal error: inPF is not native endian");
|
|
|
|
int size = 1 << inPF.bpp;
|
|
|
|
delete [] *tablep;
|
|
*tablep = new rdr::U8[size * sizeof(OUTPIXEL)];
|
|
OUTPIXEL* table = (OUTPIXEL*)*tablep;
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
int r = (i >> inPF.redShift) & inPF.redMax;
|
|
int g = (i >> inPF.greenShift) & inPF.greenMax;
|
|
int b = (i >> inPF.blueShift) & inPF.blueMax;
|
|
|
|
r = (r * (cube->nRed-1) + inPF.redMax/2) / inPF.redMax;
|
|
g = (g * (cube->nGreen-1) + inPF.greenMax/2) / inPF.greenMax;
|
|
b = (b * (cube->nBlue-1) + inPF.blueMax/2) / inPF.blueMax;
|
|
|
|
table[i] = cube->lookup(r, g, b);
|
|
}
|
|
}
|
|
|
|
void initOneRGBTableOUT (OUTPIXEL* table, int inMax, int outMax,
|
|
int outShift, bool swap)
|
|
{
|
|
int size = inMax + 1;
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
table[i] = ((i * outMax + inMax / 2) / inMax) << outShift;
|
|
#if (BPPOUT != 8)
|
|
if (swap)
|
|
table[i] = SWAPOUT (table[i]);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void initRGBTCtoTCOUT (rdr::U8** tablep, const PixelFormat& inPF,
|
|
const PixelFormat& outPF)
|
|
{
|
|
if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian)
|
|
throw Exception("Internal error: inPF is not native endian");
|
|
|
|
int size = inPF.redMax + inPF.greenMax + inPF.blueMax + 3;
|
|
|
|
delete [] *tablep;
|
|
*tablep = new rdr::U8[size * sizeof(OUTPIXEL)];
|
|
|
|
OUTPIXEL* redTable = (OUTPIXEL*)*tablep;
|
|
OUTPIXEL* greenTable = redTable + inPF.redMax + 1;
|
|
OUTPIXEL* blueTable = greenTable + inPF.greenMax + 1;
|
|
|
|
bool swap = (outPF.bigEndian != nativeBigEndian);
|
|
|
|
initOneRGBTableOUT (redTable, inPF.redMax, outPF.redMax,
|
|
outPF.redShift, swap);
|
|
initOneRGBTableOUT (greenTable, inPF.greenMax, outPF.greenMax,
|
|
outPF.greenShift, swap);
|
|
initOneRGBTableOUT (blueTable, inPF.blueMax, outPF.blueMax,
|
|
outPF.blueShift, swap);
|
|
}
|
|
|
|
|
|
void initOneRGBCubeTableOUT (OUTPIXEL* table, int inMax, int outMax,
|
|
int outMult)
|
|
{
|
|
int size = inMax + 1;
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
table[i] = ((i * outMax + inMax / 2) / inMax) * outMult;
|
|
}
|
|
}
|
|
|
|
void initRGBTCtoCubeOUT (rdr::U8** tablep, const PixelFormat& inPF,
|
|
ColourCube* cube)
|
|
{
|
|
if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian)
|
|
throw Exception("Internal error: inPF is not native endian");
|
|
|
|
int size = inPF.redMax + inPF.greenMax + inPF.blueMax + 3 + cube->size();
|
|
|
|
delete [] *tablep;
|
|
*tablep = new rdr::U8[size * sizeof(OUTPIXEL)];
|
|
|
|
OUTPIXEL* redTable = (OUTPIXEL*)*tablep;
|
|
OUTPIXEL* greenTable = redTable + inPF.redMax + 1;
|
|
OUTPIXEL* blueTable = greenTable + inPF.greenMax + 1;
|
|
OUTPIXEL* cubeTable = blueTable + inPF.blueMax + 1;
|
|
|
|
initOneRGBCubeTableOUT (redTable, inPF.redMax, cube->nRed-1,
|
|
cube->redMult());
|
|
initOneRGBCubeTableOUT (greenTable, inPF.greenMax, cube->nGreen-1,
|
|
cube->greenMult());
|
|
initOneRGBCubeTableOUT (blueTable, inPF.blueMax, cube->nBlue-1,
|
|
cube->blueMult());
|
|
for (int i = 0; i < cube->size(); i++) {
|
|
cubeTable[i] = cube->table[i];
|
|
}
|
|
}
|
|
|
|
#undef OUTPIXEL
|
|
#undef initSimpleCMtoTCOUT
|
|
#undef initSimpleTCtoTCOUT
|
|
#undef initSimpleCMtoCubeOUT
|
|
#undef initSimpleTCtoCubeOUT
|
|
#undef initRGBTCtoTCOUT
|
|
#undef initRGBTCtoCubeOUT
|
|
#undef initOneRGBTableOUT
|
|
#undef initOneRGBCubeTableOUT
|
|
}
|