blob: 73ec349b2e19d9e28406969e8e9c8653abad931e [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>
Pierre Ossmana2739342011-03-08 16:53:07 +000025#include <rfb/PixelBuffer.h>
Pierre Ossmana2739342011-03-08 16:53:07 +000026#include <rfb/PixelTransformer.h>
27
28using namespace rfb;
29
30static void noTransFn(void* table_,
Pierre Ossman654e3f92012-01-30 13:53:11 +000031 const PixelFormat& inPF, const void* inPtr, int inStride,
Pierre Ossmana2739342011-03-08 16:53:07 +000032 const PixelFormat& outPF, void* outPtr, int outStride,
33 int width, int height)
34{
35 rdr::U8* ip = (rdr::U8*)inPtr;
36 rdr::U8* op = (rdr::U8*)outPtr;
37 int inStrideBytes = inStride * (inPF.bpp/8);
38 int outStrideBytes = outStride * (outPF.bpp/8);
39 int widthBytes = width * (outPF.bpp/8);
40
41 while (height > 0) {
42 memcpy(op, ip, widthBytes);
43 ip += inStrideBytes;
44 op += outStrideBytes;
45 height--;
46 }
47}
48
49#define BPPOUT 8
50#include "transInitTempl.h"
51#define BPPIN 8
52#include "transTempl.h"
53#undef BPPIN
54#define BPPIN 16
55#include "transTempl.h"
56#undef BPPIN
57#define BPPIN 32
58#include "transTempl.h"
59#undef BPPIN
60#undef BPPOUT
61
62#define BPPOUT 16
63#include "transInitTempl.h"
64#define BPPIN 8
65#include "transTempl.h"
66#undef BPPIN
67#define BPPIN 16
68#include "transTempl.h"
69#undef BPPIN
70#define BPPIN 32
71#include "transTempl.h"
72#undef BPPIN
73#undef BPPOUT
74
75#define BPPOUT 32
76#include "transInitTempl.h"
77#define BPPIN 8
78#include "transTempl.h"
79#undef BPPIN
80#define BPPIN 16
81#include "transTempl.h"
82#undef BPPIN
83#define BPPIN 32
84#include "transTempl.h"
85#undef BPPIN
86#undef BPPOUT
87
88
89// Translation functions. Note that transSimple* is only used for 8/16bpp and
90// transRGB* is used for 16/32bpp
91
92static transFnType transSimpleFns[][3] = {
93 { transSimple8to8, transSimple8to16, transSimple8to32 },
94 { transSimple16to8, transSimple16to16, transSimple16to32 },
95};
96static transFnType transRGBFns[][3] = {
97 { transRGB16to8, transRGB16to16, transRGB16to32 },
98 { transRGB32to8, transRGB32to16, transRGB32to32 }
99};
Pierre Ossmana2739342011-03-08 16:53:07 +0000100
101// Table initialisation functions.
102
Pierre Ossmanb6b4dc62014-01-20 15:05:21 +0100103typedef void (*initFnType)(rdr::U8** tablep, const PixelFormat& inPF,
104 const PixelFormat& outPF);
Pierre Ossmana2739342011-03-08 16:53:07 +0000105
Pierre Ossmanb6b4dc62014-01-20 15:05:21 +0100106static initFnType initSimpleFns[] = {
107 initSimple8, initSimple16, initSimple32
Pierre Ossmana2739342011-03-08 16:53:07 +0000108};
109
Pierre Ossmanb6b4dc62014-01-20 15:05:21 +0100110static initFnType initRGBFns[] = {
111 initRGB8, initRGB16, initRGB32
Pierre Ossmana2739342011-03-08 16:53:07 +0000112};
113
114
115PixelTransformer::PixelTransformer(bool econ)
Pierre Ossmanb6b4dc62014-01-20 15:05:21 +0100116 : economic(econ), table(0), transFn(0)
Pierre Ossmana2739342011-03-08 16:53:07 +0000117{
118}
119
120PixelTransformer::~PixelTransformer()
121{
122 delete [] table;
123}
124
Pierre Ossmanb6b4dc62014-01-20 15:05:21 +0100125void PixelTransformer::init(const PixelFormat& inPF_,
126 const PixelFormat& outPF_)
Pierre Ossmana2739342011-03-08 16:53:07 +0000127{
128 inPF = inPF_;
Pierre Ossmana2739342011-03-08 16:53:07 +0000129 outPF = outPF_;
Pierre Ossmana2739342011-03-08 16:53:07 +0000130
131 if (table)
132 delete [] table;
133 table = NULL;
134 transFn = NULL;
135
136 if ((inPF.bpp != 8) && (inPF.bpp != 16) && (inPF.bpp != 32))
137 throw Exception("PixelTransformer: bpp in not 8, 16 or 32");
138
139 if ((outPF.bpp != 8) && (outPF.bpp != 16) && (outPF.bpp != 32))
140 throw Exception("PixelTransformer: bpp out not 8, 16 or 32");
141
Pierre Ossmana2739342011-03-08 16:53:07 +0000142 if (inPF.equal(outPF)) {
143 transFn = noTransFn;
144 return;
145 }
146
Pierre Ossmana2739342011-03-08 16:53:07 +0000147 if ((inPF.bpp > 16) || (economic && (inPF.bpp == 16))) {
148 transFn = transRGBFns[inPF.bpp/32][outPF.bpp/16];
Pierre Ossmanb6b4dc62014-01-20 15:05:21 +0100149 (*initRGBFns[outPF.bpp/16]) (&table, inPF, outPF);
Pierre Ossmana2739342011-03-08 16:53:07 +0000150 } else {
151 transFn = transSimpleFns[inPF.bpp/16][outPF.bpp/16];
Pierre Ossmanb6b4dc62014-01-20 15:05:21 +0100152 (*initSimpleFns[outPF.bpp/16]) (&table, inPF, outPF);
Pierre Ossmana2739342011-03-08 16:53:07 +0000153 }
154}
155
Pierre Ossman62ea8a22011-07-15 08:26:18 +0000156const PixelFormat &PixelTransformer::getInPF() const
157{
158 return inPF;
159}
160
Pierre Ossman62ea8a22011-07-15 08:26:18 +0000161const PixelFormat &PixelTransformer::getOutPF() const
162{
163 return outPF;
164}
165
Pierre Ossman654e3f92012-01-30 13:53:11 +0000166void PixelTransformer::translatePixels(const void* inPtr, void* outPtr,
Pierre Ossmana2739342011-03-08 16:53:07 +0000167 int nPixels) const
168{
169 if (!transFn)
170 throw Exception("PixelTransformer: not initialised yet");
171
172 (*transFn)(table, inPF, inPtr, nPixels,
173 outPF, outPtr, nPixels, nPixels, 1);
174}
175
Pierre Ossman654e3f92012-01-30 13:53:11 +0000176void PixelTransformer::translateRect(const void* inPtr, int inStride,
Pierre Ossmana2739342011-03-08 16:53:07 +0000177 Rect inRect,
178 void* outPtr, int outStride,
179 Point outCoord) const
180{
181 char *in, *out;
182
183 if (!transFn)
184 throw Exception("PixelTransformer: not initialised yet");
185
186 in = (char*)inPtr;
187 in += inPF.bpp/8 * inRect.tl.x;
188 in += (inStride * inPF.bpp/8) * inRect.tl.y;
189
190 out = (char*)outPtr;
191 out += outPF.bpp/8 * outCoord.x;
192 out += (outStride * outPF.bpp/8) * outCoord.y;
193
194 (*transFn)(table, inPF, in, inStride,
195 outPF, out, outStride,
196 inRect.width(), inRect.height());
197}
DRCffe09d62011-08-17 02:27:59 +0000198
199bool PixelTransformer::willTransform(void)
200{
201 return transFn != NULL && transFn != noTransFn;
202}