blob: c7d730f0720ca2d2dbfd1f1bcf828e07a99242dc [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#include <stdio.h>
19#include <stdlib.h>
Adam Tkac20e0d712008-11-14 14:48:21 +000020#include <string.h>
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000021#include <rfb/PixelFormat.h>
22#include <rfb/Exception.h>
23#include <rfb/ConnParams.h>
24#include <rfb/SMsgWriter.h>
25#include <rfb/ColourMap.h>
26#include <rfb/TrueColourMap.h>
27#include <rfb/PixelBuffer.h>
28#include <rfb/ColourCube.h>
29#include <rfb/TransImageGetter.h>
30
31using namespace rfb;
32
33const PixelFormat bgr233PF(8, 8, false, true, 7, 7, 3, 0, 3, 6);
34
35static void noTransFn(void* table_,
36 const PixelFormat& inPF, void* inPtr, int inStride,
37 const PixelFormat& outPF, void* outPtr, int outStride,
38 int width, int height)
39{
40 rdr::U8* ip = (rdr::U8*)inPtr;
41 rdr::U8* op = (rdr::U8*)outPtr;
42 int inStrideBytes = inStride * (inPF.bpp/8);
43 int outStrideBytes = outStride * (outPF.bpp/8);
44 int widthBytes = width * (outPF.bpp/8);
45
46 while (height > 0) {
47 memcpy(op, ip, widthBytes);
48 ip += inStrideBytes;
49 op += outStrideBytes;
50 height--;
51 }
52}
53
54#define BPPOUT 8
55#include "transInitTempl.h"
56#define BPPIN 8
57#include "transTempl.h"
58#undef BPPIN
59#define BPPIN 16
60#include "transTempl.h"
61#undef BPPIN
62#define BPPIN 32
63#include "transTempl.h"
64#undef BPPIN
65#undef BPPOUT
66
67#define BPPOUT 16
68#include "transInitTempl.h"
69#define BPPIN 8
70#include "transTempl.h"
71#undef BPPIN
72#define BPPIN 16
73#include "transTempl.h"
74#undef BPPIN
75#define BPPIN 32
76#include "transTempl.h"
77#undef BPPIN
78#undef BPPOUT
79
80#define BPPOUT 32
81#include "transInitTempl.h"
82#define BPPIN 8
83#include "transTempl.h"
84#undef BPPIN
85#define BPPIN 16
86#include "transTempl.h"
87#undef BPPIN
88#define BPPIN 32
89#include "transTempl.h"
90#undef BPPIN
91#undef BPPOUT
92
93
94// Translation functions. Note that transSimple* is only used for 8/16bpp and
95// transRGB* is used for 16/32bpp
96
97static transFnType transSimpleFns[][3] = {
98 { transSimple8to8, transSimple8to16, transSimple8to32 },
99 { transSimple16to8, transSimple16to16, transSimple16to32 },
100};
101static transFnType transRGBFns[][3] = {
102 { transRGB16to8, transRGB16to16, transRGB16to32 },
103 { transRGB32to8, transRGB32to16, transRGB32to32 }
104};
105static transFnType transRGBCubeFns[][3] = {
106 { transRGBCube16to8, transRGBCube16to16, transRGBCube16to32 },
107 { transRGBCube32to8, transRGBCube32to16, transRGBCube32to32 }
108};
109
110// Table initialisation functions.
111
112typedef void (*initCMtoTCFnType)(rdr::U8** tablep, const PixelFormat& inPF,
113 ColourMap* cm, const PixelFormat& outPF);
114typedef void (*initTCtoTCFnType)(rdr::U8** tablep, const PixelFormat& inPF,
115 const PixelFormat& outPF);
116typedef void (*initCMtoCubeFnType)(rdr::U8** tablep, const PixelFormat& inPF,
117 ColourMap* cm, ColourCube* cube);
118typedef void (*initTCtoCubeFnType)(rdr::U8** tablep, const PixelFormat& inPF,
119 ColourCube* cube);
120
121
122static initCMtoTCFnType initSimpleCMtoTCFns[] = {
123 initSimpleCMtoTC8, initSimpleCMtoTC16, initSimpleCMtoTC32
124};
125
126static initTCtoTCFnType initSimpleTCtoTCFns[] = {
127 initSimpleTCtoTC8, initSimpleTCtoTC16, initSimpleTCtoTC32
128};
129
130static initCMtoCubeFnType initSimpleCMtoCubeFns[] = {
131 initSimpleCMtoCube8, initSimpleCMtoCube16, initSimpleCMtoCube32
132};
133
134static initTCtoCubeFnType initSimpleTCtoCubeFns[] = {
135 initSimpleTCtoCube8, initSimpleTCtoCube16, initSimpleTCtoCube32
136};
137
138static initTCtoTCFnType initRGBTCtoTCFns[] = {
139 initRGBTCtoTC8, initRGBTCtoTC16, initRGBTCtoTC32
140};
141
142static initTCtoCubeFnType initRGBTCtoCubeFns[] = {
143 initRGBTCtoCube8, initRGBTCtoCube16, initRGBTCtoCube32
144};
145
146
147TransImageGetter::TransImageGetter(bool econ)
148 : economic(econ), pb(0), table(0), transFn(0), cube(0)
149{
150}
151
152TransImageGetter::~TransImageGetter()
153{
154 delete [] table;
155}
156
157void TransImageGetter::init(PixelBuffer* pb_, const PixelFormat& out,
158 SMsgWriter* writer, ColourCube* cube_)
159{
160 pb = pb_;
161 outPF = out;
162 transFn = 0;
163 cube = cube_;
164 const PixelFormat& inPF = pb->getPF();
165
166 if ((inPF.bpp != 8) && (inPF.bpp != 16) && (inPF.bpp != 32))
167 throw Exception("TransImageGetter: bpp in not 8, 16 or 32");
168
169 if ((outPF.bpp != 8) && (outPF.bpp != 16) && (outPF.bpp != 32))
170 throw Exception("TransImageGetter: bpp out not 8, 16 or 32");
171
172 if (!outPF.trueColour) {
173 if (outPF.bpp != 8)
174 throw Exception("TransImageGetter: outPF has color map but not 8bpp");
175
176 if (!inPF.trueColour) {
177 if (inPF.bpp != 8)
178 throw Exception("TransImageGetter: inPF has colorMap but not 8bpp");
179
180 // CM to CM/Cube
181
182 if (cube) {
183 transFn = transSimpleFns[inPF.bpp/16][outPF.bpp/16];
184 (*initSimpleCMtoCubeFns[outPF.bpp/16]) (&table, inPF,
185 pb->getColourMap(), cube);
186 } else {
187 transFn = noTransFn;
188 setColourMapEntries(0, 256, writer);
189 }
190 return;
191 }
192
193 // TC to CM/Cube
194
195 ColourCube defaultCube(6,6,6);
196 if (!cube) cube = &defaultCube;
197
198 if ((inPF.bpp > 16) || (economic && (inPF.bpp == 16))) {
199 transFn = transRGBCubeFns[inPF.bpp/32][outPF.bpp/16];
200 (*initRGBTCtoCubeFns[outPF.bpp/16]) (&table, inPF, cube);
201 } else {
202 transFn = transSimpleFns[inPF.bpp/16][outPF.bpp/16];
203 (*initSimpleTCtoCubeFns[outPF.bpp/16]) (&table, inPF, cube);
204 }
205
206 if (cube != &defaultCube)
207 return;
208
209 if (writer) writer->writeSetColourMapEntries(0, 216, cube);
210 cube = 0;
211 return;
212 }
213
214 if (inPF.equal(outPF)) {
215 transFn = noTransFn;
216 return;
217 }
218
219 if (!inPF.trueColour) {
220
221 // CM to TC
222
223 if (inPF.bpp != 8)
224 throw Exception("TransImageGetter: inPF has colorMap but not 8bpp");
225 transFn = transSimpleFns[inPF.bpp/16][outPF.bpp/16];
226 (*initSimpleCMtoTCFns[outPF.bpp/16]) (&table, inPF, pb->getColourMap(),
227 outPF);
228 return;
229 }
230
231 // TC to TC
232
233 if ((inPF.bpp > 16) || (economic && (inPF.bpp == 16))) {
234 transFn = transRGBFns[inPF.bpp/32][outPF.bpp/16];
235 (*initRGBTCtoTCFns[outPF.bpp/16]) (&table, inPF, outPF);
236 } else {
237 transFn = transSimpleFns[inPF.bpp/16][outPF.bpp/16];
238 (*initSimpleTCtoTCFns[outPF.bpp/16]) (&table, inPF, outPF);
239 }
240}
241
242void TransImageGetter::setColourMapEntries(int firstCol, int nCols,
243 SMsgWriter* writer)
244{
245 if (nCols == 0)
246 nCols = (1 << pb->getPF().depth) - firstCol;
247 if (pb->getPF().trueColour) return; // shouldn't be called in this case
248
249 if (outPF.trueColour) {
250 (*initSimpleCMtoTCFns[outPF.bpp/16]) (&table, pb->getPF(),
251 pb->getColourMap(), outPF);
252 } else if (cube) {
253 (*initSimpleCMtoCubeFns[outPF.bpp/16]) (&table, pb->getPF(),
254 pb->getColourMap(), cube);
255 } else if (writer && pb->getColourMap()) {
256 writer->writeSetColourMapEntries(firstCol, nCols, pb->getColourMap());
257 }
258}
259
260void TransImageGetter::getImage(void* outPtr, const Rect& r, int outStride)
261{
262 if (!transFn)
263 throw Exception("TransImageGetter: not initialised yet");
264
265 int inStride;
266 const rdr::U8* inPtr = pb->getPixelsR(r.translate(offset.negate()), &inStride);
267
268 if (!outStride) outStride = r.width();
269
270 (*transFn)(table, pb->getPF(), (void*)inPtr, inStride,
271 outPF, outPtr, outStride, r.width(), r.height());
272}
273
274void TransImageGetter::translatePixels(void* inPtr, void* outPtr,
275 int nPixels) const
276{
277 (*transFn)(table, pb->getPF(), inPtr, nPixels,
278 outPF, outPtr, nPixels, nPixels, 1);
279}