blob: c737f4d9dee94f4029f94131252c3b8e650dec14 [file] [log] [blame]
Pierre Ossmana2739342011-03-08 16:53:07 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
2 * Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
DRCffe09d62011-08-17 02:27:59 +00003 * Copyright (C) 2011 D. R. Commander. All Rights Reserved.
Pierre Ossmana2739342011-03-08 16:53:07 +00004 *
5 * This is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This software is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this software; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18 * USA.
19 */
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <rfb/PixelFormat.h>
24#include <rfb/Exception.h>
25#include <rfb/ColourMap.h>
26#include <rfb/TrueColourMap.h>
27#include <rfb/PixelBuffer.h>
28#include <rfb/ColourCube.h>
29#include <rfb/PixelTransformer.h>
30
31using namespace rfb;
32
33static 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
145PixelTransformer::PixelTransformer(bool econ)
146 : economic(econ), cmCallback(0), table(0), transFn(0), cube(0)
147{
148}
149
150PixelTransformer::~PixelTransformer()
151{
152 delete [] table;
153}
154
155void PixelTransformer::init(const PixelFormat& inPF_, ColourMap* inCM_,
156 const PixelFormat& outPF_, ColourCube* cube_,
157 setCMFnType cmCallback_, void *cbData_)
158{
159 inPF = inPF_;
160 inCM = inCM_;
161
162 outPF = outPF_;
163 cube = cube_;
164 cmCallback = cmCallback_;
165 cbData = cbData_;
166
167 if (table)
168 delete [] table;
169 table = NULL;
170 transFn = NULL;
171
172 if ((inPF.bpp != 8) && (inPF.bpp != 16) && (inPF.bpp != 32))
173 throw Exception("PixelTransformer: bpp in not 8, 16 or 32");
174
175 if ((outPF.bpp != 8) && (outPF.bpp != 16) && (outPF.bpp != 32))
176 throw Exception("PixelTransformer: bpp out not 8, 16 or 32");
177
178 if (!outPF.trueColour) {
179 if (outPF.bpp != 8)
180 throw Exception("PixelTransformer: outPF has color map but not 8bpp");
181
182 if (!inPF.trueColour) {
183 if (inPF.bpp != 8)
184 throw Exception("PixelTransformer: inPF has colorMap but not 8bpp");
185 if (!inCM)
186 throw Exception("PixelTransformer: inPF has colorMap but no colour map specified");
187
188 // CM to CM/Cube
189
190 if (cube) {
191 transFn = transSimpleFns[0][0];
192 (*initSimpleCMtoCubeFns[0]) (&table, inPF, inCM, cube);
193 } else {
194 transFn = noTransFn;
195 setColourMapEntries(0, 256);
196 }
197 return;
198 }
199
200 // TC to CM/Cube
201
202 ColourCube defaultCube(6,6,6);
203 if (!cube) cube = &defaultCube;
204
205 if ((inPF.bpp > 16) || (economic && (inPF.bpp == 16))) {
206 transFn = transRGBCubeFns[inPF.bpp/32][0];
207 (*initRGBTCtoCubeFns[0]) (&table, inPF, cube);
208 } else {
209 transFn = transSimpleFns[inPF.bpp/16][0];
210 (*initSimpleTCtoCubeFns[0]) (&table, inPF, cube);
211 }
212
213 if (cube != &defaultCube)
214 return;
215
216 if (!cmCallback)
217 throw Exception("PixelTransformer: Neither colour map callback nor colour cube provided");
218
219 cmCallback(0, 216, cube, cbData);
220 cube = 0;
221 return;
222 }
223
224 if (inPF.equal(outPF)) {
225 transFn = noTransFn;
226 return;
227 }
228
229 if (!inPF.trueColour) {
230
231 // CM to TC
232
233 if (inPF.bpp != 8)
234 throw Exception("PixelTransformer: inPF has colorMap but not 8bpp");
235 if (!inCM)
236 throw Exception("PixelTransformer: inPF has colorMap but no colour map specified");
237
238 transFn = transSimpleFns[0][outPF.bpp/16];
239 (*initSimpleCMtoTCFns[outPF.bpp/16]) (&table, inPF, inCM, outPF);
240 return;
241 }
242
243 // TC to TC
244
245 if ((inPF.bpp > 16) || (economic && (inPF.bpp == 16))) {
246 transFn = transRGBFns[inPF.bpp/32][outPF.bpp/16];
247 (*initRGBTCtoTCFns[outPF.bpp/16]) (&table, inPF, outPF);
248 } else {
249 transFn = transSimpleFns[inPF.bpp/16][outPF.bpp/16];
250 (*initSimpleTCtoTCFns[outPF.bpp/16]) (&table, inPF, outPF);
251 }
252}
253
Pierre Ossman62ea8a22011-07-15 08:26:18 +0000254const PixelFormat &PixelTransformer::getInPF() const
255{
256 return inPF;
257}
258
259const ColourMap *PixelTransformer::getInColourMap() const
260{
261 return inCM;
262}
263
264const PixelFormat &PixelTransformer::getOutPF() const
265{
266 return outPF;
267}
268
269const ColourCube *PixelTransformer::getOutColourCube() const
270{
271 return cube;
272}
273
Pierre Ossmana2739342011-03-08 16:53:07 +0000274void PixelTransformer::setColourMapEntries(int firstCol, int nCols)
275{
276 if (nCols == 0)
277 nCols = (1 << inPF.depth) - firstCol;
278
279 if (inPF.trueColour) return; // shouldn't be called in this case
280
281 if (outPF.trueColour) {
282 (*initSimpleCMtoTCFns[outPF.bpp/16]) (&table, inPF, inCM, outPF);
283 } else if (cube) {
284 (*initSimpleCMtoCubeFns[outPF.bpp/16]) (&table, inPF, inCM, cube);
285 } else {
286 if (!cmCallback)
287 throw Exception("PixelTransformer: Neither colour map callback nor colour cube provided");
288 cmCallback(firstCol, nCols, inCM, cbData);
289 }
290}
291
292void PixelTransformer::translatePixels(void* inPtr, void* outPtr,
293 int nPixels) const
294{
295 if (!transFn)
296 throw Exception("PixelTransformer: not initialised yet");
297
298 (*transFn)(table, inPF, inPtr, nPixels,
299 outPF, outPtr, nPixels, nPixels, 1);
300}
301
302void PixelTransformer::translateRect(void* inPtr, int inStride,
303 Rect inRect,
304 void* outPtr, int outStride,
305 Point outCoord) const
306{
307 char *in, *out;
308
309 if (!transFn)
310 throw Exception("PixelTransformer: not initialised yet");
311
312 in = (char*)inPtr;
313 in += inPF.bpp/8 * inRect.tl.x;
314 in += (inStride * inPF.bpp/8) * inRect.tl.y;
315
316 out = (char*)outPtr;
317 out += outPF.bpp/8 * outCoord.x;
318 out += (outStride * outPF.bpp/8) * outCoord.y;
319
320 (*transFn)(table, inPF, in, inStride,
321 outPF, out, outStride,
322 inRect.width(), inRect.height());
323}
DRCffe09d62011-08-17 02:27:59 +0000324
325bool PixelTransformer::willTransform(void)
326{
327 return transFn != NULL && transFn != noTransFn;
328}