/[rdesktop]/sourceforge.net/trunk/rdesktop/bitmap.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/trunk/rdesktop/bitmap.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 36 - (show annotations)
Sat Sep 15 14:30:46 2001 UTC (22 years, 7 months ago) by matty
File MIME type: text/plain
File size: 5024 byte(s)
OSF1/Alpha build fixes.

1 /*
2 rdesktop: A Remote Desktop Protocol client.
3 Bitmap decompression routines
4 Copyright (C) Matthew Chapman 1999-2001
5
6 This program 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 program 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 program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "rdesktop.h"
22
23 #define CVAL(p) (*(p++))
24
25 #define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
26
27 #define REPEAT(statement) \
28 { \
29 while((count & ~0x7) && ((x+8) < width)) \
30 UNROLL8( statement; count--; x++; ); \
31 \
32 while((count > 0) && (x < width)) { statement; count--; x++; } \
33 }
34
35 #define MASK_UPDATE() \
36 { \
37 mixmask <<= 1; \
38 if (mixmask == 0) \
39 { \
40 mask = fom_mask ? fom_mask : CVAL(input); \
41 mixmask = 1; \
42 } \
43 }
44
45 BOOL
46 bitmap_decompress(unsigned char *output, int width, int height,
47 unsigned char *input, int size)
48 {
49 unsigned char *end = input + size;
50 unsigned char *prevline = NULL, *line = NULL;
51 int opcode, count, offset, isfillormix, x = width;
52 int lastopcode = -1, insertmix = False, bicolour = False;
53 uint8 code, colour1 = 0, colour2 = 0;
54 uint8 mixmask, mask = 0, mix = 0xff;
55 int fom_mask = 0;
56
57 while (input < end)
58 {
59 fom_mask = 0;
60 code = CVAL(input);
61 opcode = code >> 4;
62
63 /* Handle different opcode forms */
64 switch (opcode)
65 {
66 case 0xc:
67 case 0xd:
68 case 0xe:
69 opcode -= 6;
70 count = code & 0xf;
71 offset = 16;
72 break;
73
74 case 0xf:
75 opcode = code & 0xf;
76 if (opcode < 9)
77 {
78 count = CVAL(input);
79 count |= CVAL(input) << 8;
80 }
81 else
82 {
83 count = (opcode < 0xb) ? 8 : 1;
84 }
85 offset = 0;
86 break;
87
88 default:
89 opcode >>= 1;
90 count = code & 0x1f;
91 offset = 32;
92 break;
93 }
94
95 /* Handle strange cases for counts */
96 if (offset != 0)
97 {
98 isfillormix = ((opcode == 2) || (opcode == 7));
99
100 if (count == 0)
101 {
102 if (isfillormix)
103 count = CVAL(input) + 1;
104 else
105 count = CVAL(input) + offset;
106 }
107 else if (isfillormix)
108 {
109 count <<= 3;
110 }
111 }
112
113 /* Read preliminary data */
114 switch (opcode)
115 {
116 case 0: /* Fill */
117 if ((lastopcode == opcode)
118 && !((x == width) && (prevline == NULL)))
119 insertmix = True;
120 break;
121 case 8: /* Bicolour */
122 colour1 = CVAL(input);
123 case 3: /* Colour */
124 colour2 = CVAL(input);
125 break;
126 case 6: /* SetMix/Mix */
127 case 7: /* SetMix/FillOrMix */
128 mix = CVAL(input);
129 opcode -= 5;
130 break;
131 case 9: /* FillOrMix_1 */
132 mask = 0x03;
133 opcode = 0x02;
134 fom_mask = 3;
135 break;
136 case 0x0a: /* FillOrMix_2 */
137 mask = 0x05;
138 opcode = 0x02;
139 fom_mask = 5;
140 break;
141
142 }
143
144 lastopcode = opcode;
145 mixmask = 0;
146
147 /* Output body */
148 while (count > 0)
149 {
150 if (x >= width)
151 {
152 if (height <= 0)
153 return False;
154
155 x = 0;
156 height--;
157
158 prevline = line;
159 line = output + height * width;
160 }
161
162 switch (opcode)
163 {
164 case 0: /* Fill */
165 if (insertmix)
166 {
167 if (prevline == NULL)
168 line[x] = mix;
169 else
170 line[x] =
171 prevline[x] ^
172 mix;
173
174 insertmix = False;
175 count--;
176 x++;
177 }
178
179 if (prevline == NULL)
180 {
181 REPEAT(line[x] = 0);
182 }
183 else
184 {
185 REPEAT(line[x] = prevline[x]);
186 }
187 break;
188
189 case 1: /* Mix */
190 if (prevline == NULL)
191 {
192 REPEAT(line[x] = mix);
193 }
194 else
195 {
196 REPEAT(line[x] =
197 prevline[x] ^ mix);
198 }
199 break;
200
201 case 2: /* Fill or Mix */
202 if (prevline == NULL)
203 {
204 REPEAT(MASK_UPDATE();
205 if (mask & mixmask)
206 line[x] = mix;
207 else
208 line[x] = 0;);
209 }
210 else
211 {
212 REPEAT(MASK_UPDATE();
213 if (mask & mixmask)
214 line[x] =
215 prevline[x] ^ mix;
216 else
217 line[x] =
218 prevline[x];);
219 }
220 break;
221
222 case 3: /* Colour */
223 REPEAT(line[x] = colour2);
224 break;
225
226 case 4: /* Copy */
227 REPEAT(line[x] = CVAL(input));
228 break;
229
230 case 8: /* Bicolour */
231 REPEAT(if (bicolour)
232 {
233 line[x] = colour2;
234 bicolour = False;}
235 else
236 {
237 line[x] = colour1;
238 bicolour = True; count++;}
239 );
240 break;
241
242 case 0xd: /* White */
243 REPEAT(line[x] = 0xff);
244 break;
245
246 case 0xe: /* Black */
247 REPEAT(line[x] = 0x00);
248 break;
249
250 default:
251 unimpl("bitmap opcode 0x%x\n",
252 opcode);
253 return False;
254 }
255 }
256 }
257
258 return True;
259 }

  ViewVC Help
Powered by ViewVC 1.1.26