blob: b6e86ed5ea0bf3b3ea92e8f807d29ba8b21a920f [file] [log] [blame]
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +00001/* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved.
Peter Åstrandd69bcc42011-09-28 12:52:53 +00002 * Copyright 2004-2005 Cendio AB.
Pierre Ossman80b42092015-11-10 17:17:34 +01003 * Copyright 2009-2015 Pierre Ossman for Cendio AB
DRC33c15e32011-11-03 18:49:21 +00004 * Copyright (C) 2011 D. R. Commander. All Rights Reserved.
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +00005 *
6 * This is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This software is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this software; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 * USA.
20 */
21
22//
23// Tight decoding functions.
24//
Pierre Ossmanbcc295e2014-02-12 13:16:43 +010025// This file is #included after having set the following macro:
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000026// BPP - 8, 16 or 32
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000027
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000028namespace rfb {
29
30// CONCAT2E concatenates its arguments, expanding them if they are macros
31
32#ifndef CONCAT2E
33#define CONCAT2(a,b) a##b
34#define CONCAT2E(a,b) CONCAT2(a,b)
35#endif
36
37#define PIXEL_T rdr::CONCAT2E(U,BPP)
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000038
39#if BPP == 32
40
DRC33c15e32011-11-03 18:49:21 +000041void
Pierre Ossman80b42092015-11-10 17:17:34 +010042TightDecoder::FilterGradient24(const rdr::U8 *inbuf,
43 const PixelFormat& pf, PIXEL_T* outbuf,
44 int stride, const Rect& r)
45{
46 int x, y, c;
47 rdr::U8 prevRow[TIGHT_MAX_WIDTH*3];
48 rdr::U8 thisRow[TIGHT_MAX_WIDTH*3];
49 rdr::U8 pix[3];
50 int est[3];
51
52 memset(prevRow, 0, sizeof(prevRow));
53
54 // Set up shortcut variables
55 int rectHeight = r.height();
56 int rectWidth = r.width();
57
58 for (y = 0; y < rectHeight; y++) {
59 /* First pixel in a row */
60 for (c = 0; c < 3; c++) {
61 pix[c] = inbuf[y*rectWidth*3+c] + prevRow[c];
62 thisRow[c] = pix[c];
63 }
64 pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride], pix, 1);
65
66 /* Remaining pixels of a row */
67 for (x = 1; x < rectWidth; x++) {
68 for (c = 0; c < 3; c++) {
69 est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c];
70 if (est[c] > 0xff) {
71 est[c] = 0xff;
72 } else if (est[c] < 0) {
73 est[c] = 0;
74 }
75 pix[c] = inbuf[(y*rectWidth+x)*3+c] + est[c];
76 thisRow[x*3+c] = pix[c];
77 }
78 pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride+x], pix, 1);
79 }
80
81 memcpy(prevRow, thisRow, sizeof(prevRow));
82 }
83}
84
85#endif
86
87#if BPP != 8
88
89void TightDecoder::FilterGradient(const rdr::U8* inbuf,
90 const PixelFormat& pf, PIXEL_T* outbuf,
91 int stride, const Rect& r)
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000092{
93 int x, y, c;
94 static rdr::U8 prevRow[TIGHT_MAX_WIDTH*3];
95 static rdr::U8 thisRow[TIGHT_MAX_WIDTH*3];
96 rdr::U8 pix[3];
97 int est[3];
98
99 memset(prevRow, 0, sizeof(prevRow));
100
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000101 // Set up shortcut variables
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000102 int rectHeight = r.height();
103 int rectWidth = r.width();
104
105 for (y = 0; y < rectHeight; y++) {
106 /* First pixel in a row */
Pierre Ossman80b42092015-11-10 17:17:34 +0100107 pf.rgbFromBuffer(pix, &inbuf[y*rectWidth], 1);
Pierre Ossman67b2b2f2009-03-06 10:12:55 +0000108 for (c = 0; c < 3; c++)
109 pix[c] += prevRow[c];
110
111 memcpy(thisRow, pix, sizeof(pix));
112
Pierre Ossman80b42092015-11-10 17:17:34 +0100113 pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride], pix, 1);
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000114
115 /* Remaining pixels of a row */
116 for (x = 1; x < rectWidth; x++) {
117 for (c = 0; c < 3; c++) {
Pierre Ossman67b2b2f2009-03-06 10:12:55 +0000118 est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c];
119 if (est[c] > 255) {
120 est[c] = 255;
121 } else if (est[c] < 0) {
122 est[c] = 0;
123 }
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000124 }
Pierre Ossman67b2b2f2009-03-06 10:12:55 +0000125
Pierre Ossman80b42092015-11-10 17:17:34 +0100126 pf.rgbFromBuffer(pix, &inbuf[y*rectWidth+x], 1);
Pierre Ossman67b2b2f2009-03-06 10:12:55 +0000127 for (c = 0; c < 3; c++)
128 pix[c] += est[c];
129
130 memcpy(&thisRow[x*3], pix, sizeof(pix));
131
Pierre Ossman80b42092015-11-10 17:17:34 +0100132 pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride+x], pix, 1);
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000133 }
134
135 memcpy(prevRow, thisRow, sizeof(prevRow));
136 }
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000137}
138
Pierre Ossman80b42092015-11-10 17:17:34 +0100139#endif
140
141void TightDecoder::FilterPalette(const PIXEL_T* palette, int palSize,
142 const rdr::U8* inbuf, PIXEL_T* outbuf,
143 int stride, const Rect& r)
144{
145 // Indexed color
146 int x, h = r.height(), w = r.width(), b, pad = stride - w;
147 PIXEL_T* ptr = outbuf;
148 rdr::U8 bits;
149 const rdr::U8* srcPtr = inbuf;
150 if (palSize <= 2) {
151 // 2-color palette
152 while (h > 0) {
153 for (x = 0; x < w / 8; x++) {
154 bits = *srcPtr++;
155 for (b = 7; b >= 0; b--) {
156 *ptr++ = palette[bits >> b & 1];
157 }
158 }
159 if (w % 8 != 0) {
160 bits = *srcPtr++;
161 for (b = 7; b >= 8 - w % 8; b--) {
162 *ptr++ = palette[bits >> b & 1];
163 }
164 }
165 ptr += pad;
166 h--;
167 }
168 } else {
169 // 256-color palette
170 while (h > 0) {
171 PIXEL_T *endOfRow = ptr + w;
172 while (ptr < endOfRow) {
173 *ptr++ = palette[*srcPtr++];
174 }
175 ptr += pad;
176 h--;
177 }
178 }
179}
180
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000181#undef PIXEL_T
182}