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