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