blob: 464cfdfcccdb507770a4a16015acd27c76e481ff [file] [log] [blame]
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18//
19// transInitTempl.h - templates for functions to initialise lookup tables for
20// the translation functions.
21//
22// This file is #included after having set the following macros:
23// BPPOUT - 8, 16 or 32
24
25#if !defined(BPPOUT)
26#error "transInitTempl.h: BPPOUT not defined"
27#endif
28
29namespace rfb {
30
31// CONCAT2E concatenates its arguments, expanding them if they are macros
32
33#ifndef CONCAT2E
34#define CONCAT2(a,b) a##b
35#define CONCAT2E(a,b) CONCAT2(a,b)
36#endif
37
38#ifndef SWAP16
39#define SWAP16(n) ((((n) & 0xff) << 8) | (((n) >> 8) & 0xff))
40#endif
41
42#ifndef SWAP32
43#define SWAP32(n) (((n) >> 24) | (((n) & 0x00ff0000) >> 8) | \
44 (((n) & 0x0000ff00) << 8) | ((n) << 24))
45#endif
46
47#define OUTPIXEL rdr::CONCAT2E(U,BPPOUT)
48#define SWAPOUT CONCAT2E(SWAP,BPPOUT)
49#define initSimpleCMtoTCOUT CONCAT2E(initSimpleCMtoTC,BPPOUT)
50#define initSimpleTCtoTCOUT CONCAT2E(initSimpleTCtoTC,BPPOUT)
51#define initSimpleCMtoCubeOUT CONCAT2E(initSimpleCMtoCube,BPPOUT)
52#define initSimpleTCtoCubeOUT CONCAT2E(initSimpleTCtoCube,BPPOUT)
53#define initRGBTCtoTCOUT CONCAT2E(initRGBTCtoTC,BPPOUT)
54#define initRGBTCtoCubeOUT CONCAT2E(initRGBTCtoCube,BPPOUT)
55#define initOneRGBTableOUT CONCAT2E(initOneRGBTable,BPPOUT)
56#define initOneRGBCubeTableOUT CONCAT2E(initOneRGBCubeTable,BPPOUT)
57
58#ifndef TRANS_INIT_TEMPL_ENDIAN_TEST
59#define TRANS_INIT_TEMPL_ENDIAN_TEST
60 static rdr::U32 endianTest = 1;
61 static bool nativeBigEndian = *(rdr::U8*)(&endianTest) != 1;
62#endif
63
64void initSimpleCMtoTCOUT (rdr::U8** tablep, const PixelFormat& inPF,
65 ColourMap* cm, const PixelFormat& outPF)
66{
67 if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian)
68 throw Exception("Internal error: inPF is not native endian");
69
70 int size = 1 << inPF.bpp;
71
72 delete [] *tablep;
73 *tablep = new rdr::U8[size * sizeof(OUTPIXEL)];
74 OUTPIXEL* table = (OUTPIXEL*)*tablep;
75
76 for (int i = 0; i < size; i++) {
77 int r,g,b;
78 cm->lookup(i,&r,&g,&b);
79
80 table[i] = ((((r * outPF.redMax + 32767) / 65535) << outPF.redShift) |
81 (((g * outPF.greenMax + 32767) / 65535) << outPF.greenShift) |
82 (((b * outPF.blueMax + 32767) / 65535) << outPF.blueShift));
83#if (BPPOUT != 8)
84 if (outPF.bigEndian != nativeBigEndian)
85 table[i] = SWAPOUT (table[i]);
86#endif
87 }
88}
89
90void initSimpleTCtoTCOUT (rdr::U8** tablep, const PixelFormat& inPF,
91 const PixelFormat& outPF)
92{
93 if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian)
94 throw Exception("Internal error: inPF is not native endian");
95
96 int size = 1 << inPF.bpp;
97
98 delete [] *tablep;
99 *tablep = new rdr::U8[size * sizeof(OUTPIXEL)];
100 OUTPIXEL* table = (OUTPIXEL*)*tablep;
101
102 for (int i = 0; i < size; i++) {
103 int r = (i >> inPF.redShift) & inPF.redMax;
104 int g = (i >> inPF.greenShift) & inPF.greenMax;
105 int b = (i >> inPF.blueShift) & inPF.blueMax;
106
107 r = (r * outPF.redMax + inPF.redMax/2) / inPF.redMax;
108 g = (g * outPF.greenMax + inPF.greenMax/2) / inPF.greenMax;
109 b = (b * outPF.blueMax + inPF.blueMax/2) / inPF.blueMax;
110
111 table[i] = ((r << outPF.redShift) |
112 (g << outPF.greenShift) |
113 (b << outPF.blueShift));
114#if (BPPOUT != 8)
115 if (outPF.bigEndian != nativeBigEndian)
116 table[i] = SWAPOUT (table[i]);
117#endif
118 }
119}
120
121void initSimpleCMtoCubeOUT (rdr::U8** tablep, const PixelFormat& inPF,
122 ColourMap* cm, ColourCube* cube)
123{
124 if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian)
125 throw Exception("Internal error: inPF is not native endian");
126
127 int size = 1 << inPF.bpp;
128
129 delete [] *tablep;
130 *tablep = new rdr::U8[size * sizeof(OUTPIXEL)];
131 OUTPIXEL* table = (OUTPIXEL*)*tablep;
132
133 for (int i = 0; i < size; i++) {
134 int r,g,b;
135 cm->lookup(i,&r,&g,&b);
136 r = (r * (cube->nRed-1) + 32767) / 65535;
137 g = (g * (cube->nGreen-1) + 32767) / 65535;
138 b = (b * (cube->nBlue-1) + 32767) / 65535;
139 table[i] = cube->lookup(r, g, b);
140 }
141}
142
143void initSimpleTCtoCubeOUT (rdr::U8** tablep, const PixelFormat& inPF,
144 ColourCube* cube)
145{
146 if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian)
147 throw Exception("Internal error: inPF is not native endian");
148
149 int size = 1 << inPF.bpp;
150
151 delete [] *tablep;
152 *tablep = new rdr::U8[size * sizeof(OUTPIXEL)];
153 OUTPIXEL* table = (OUTPIXEL*)*tablep;
154
155 for (int i = 0; i < size; i++) {
156 int r = (i >> inPF.redShift) & inPF.redMax;
157 int g = (i >> inPF.greenShift) & inPF.greenMax;
158 int b = (i >> inPF.blueShift) & inPF.blueMax;
159
160 r = (r * (cube->nRed-1) + inPF.redMax/2) / inPF.redMax;
161 g = (g * (cube->nGreen-1) + inPF.greenMax/2) / inPF.greenMax;
162 b = (b * (cube->nBlue-1) + inPF.blueMax/2) / inPF.blueMax;
163
164 table[i] = cube->lookup(r, g, b);
165 }
166}
167
168void initOneRGBTableOUT (OUTPIXEL* table, int inMax, int outMax,
169 int outShift, bool swap)
170{
171 int size = inMax + 1;
172
173 for (int i = 0; i < size; i++) {
174 table[i] = ((i * outMax + inMax / 2) / inMax) << outShift;
175#if (BPPOUT != 8)
176 if (swap)
177 table[i] = SWAPOUT (table[i]);
178#endif
179 }
180}
181
182void initRGBTCtoTCOUT (rdr::U8** tablep, const PixelFormat& inPF,
183 const PixelFormat& outPF)
184{
185 if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian)
186 throw Exception("Internal error: inPF is not native endian");
187
188 int size = inPF.redMax + inPF.greenMax + inPF.blueMax + 3;
189
190 delete [] *tablep;
191 *tablep = new rdr::U8[size * sizeof(OUTPIXEL)];
192
193 OUTPIXEL* redTable = (OUTPIXEL*)*tablep;
194 OUTPIXEL* greenTable = redTable + inPF.redMax + 1;
195 OUTPIXEL* blueTable = greenTable + inPF.greenMax + 1;
196
197 bool swap = (outPF.bigEndian != nativeBigEndian);
198
199 initOneRGBTableOUT (redTable, inPF.redMax, outPF.redMax,
200 outPF.redShift, swap);
201 initOneRGBTableOUT (greenTable, inPF.greenMax, outPF.greenMax,
202 outPF.greenShift, swap);
203 initOneRGBTableOUT (blueTable, inPF.blueMax, outPF.blueMax,
204 outPF.blueShift, swap);
205}
206
207
208void initOneRGBCubeTableOUT (OUTPIXEL* table, int inMax, int outMax,
209 int outMult)
210{
211 int size = inMax + 1;
212
213 for (int i = 0; i < size; i++) {
214 table[i] = ((i * outMax + inMax / 2) / inMax) * outMult;
215 }
216}
217
218void initRGBTCtoCubeOUT (rdr::U8** tablep, const PixelFormat& inPF,
219 ColourCube* cube)
220{
221 if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian)
222 throw Exception("Internal error: inPF is not native endian");
223
224 int size = inPF.redMax + inPF.greenMax + inPF.blueMax + 3 + cube->size();
225
226 delete [] *tablep;
227 *tablep = new rdr::U8[size * sizeof(OUTPIXEL)];
228
229 OUTPIXEL* redTable = (OUTPIXEL*)*tablep;
230 OUTPIXEL* greenTable = redTable + inPF.redMax + 1;
231 OUTPIXEL* blueTable = greenTable + inPF.greenMax + 1;
232 OUTPIXEL* cubeTable = blueTable + inPF.blueMax + 1;
233
234 initOneRGBCubeTableOUT (redTable, inPF.redMax, cube->nRed-1,
235 cube->redMult());
236 initOneRGBCubeTableOUT (greenTable, inPF.greenMax, cube->nGreen-1,
237 cube->greenMult());
238 initOneRGBCubeTableOUT (blueTable, inPF.blueMax, cube->nBlue-1,
239 cube->blueMult());
240 for (int i = 0; i < cube->size(); i++) {
241 cubeTable[i] = cube->table[i];
242 }
243}
244
245#undef OUTPIXEL
246#undef initSimpleCMtoTCOUT
247#undef initSimpleTCtoTCOUT
248#undef initSimpleCMtoCubeOUT
249#undef initSimpleTCtoCubeOUT
250#undef initRGBTCtoTCOUT
251#undef initRGBTCtoCubeOUT
252#undef initOneRGBTableOUT
253#undef initOneRGBCubeTableOUT
254}