/[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 82 - (show annotations)
Tue Jul 30 07:18:48 2002 UTC (21 years, 9 months ago) by astrand
File MIME type: text/plain
File size: 4908 byte(s)
Changed max line length to 100

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, unsigned char *input, int size)
47 {
48 unsigned char *end = input + size;
49 unsigned char *prevline = NULL, *line = NULL;
50 int opcode, count, offset, isfillormix, x = width;
51 int lastopcode = -1, insertmix = False, bicolour = False;
52 uint8 code, colour1 = 0, colour2 = 0;
53 uint8 mixmask, mask = 0, mix = 0xff;
54 int fom_mask = 0;
55
56 while (input < end)
57 {
58 fom_mask = 0;
59 code = CVAL(input);
60 opcode = code >> 4;
61
62 /* Handle different opcode forms */
63 switch (opcode)
64 {
65 case 0xc:
66 case 0xd:
67 case 0xe:
68 opcode -= 6;
69 count = code & 0xf;
70 offset = 16;
71 break;
72
73 case 0xf:
74 opcode = code & 0xf;
75 if (opcode < 9)
76 {
77 count = CVAL(input);
78 count |= CVAL(input) << 8;
79 }
80 else
81 {
82 count = (opcode < 0xb) ? 8 : 1;
83 }
84 offset = 0;
85 break;
86
87 default:
88 opcode >>= 1;
89 count = code & 0x1f;
90 offset = 32;
91 break;
92 }
93
94 /* Handle strange cases for counts */
95 if (offset != 0)
96 {
97 isfillormix = ((opcode == 2) || (opcode == 7));
98
99 if (count == 0)
100 {
101 if (isfillormix)
102 count = CVAL(input) + 1;
103 else
104 count = CVAL(input) + offset;
105 }
106 else if (isfillormix)
107 {
108 count <<= 3;
109 }
110 }
111
112 /* Read preliminary data */
113 switch (opcode)
114 {
115 case 0: /* Fill */
116 if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
117 insertmix = True;
118 break;
119 case 8: /* Bicolour */
120 colour1 = CVAL(input);
121 case 3: /* Colour */
122 colour2 = CVAL(input);
123 break;
124 case 6: /* SetMix/Mix */
125 case 7: /* SetMix/FillOrMix */
126 mix = CVAL(input);
127 opcode -= 5;
128 break;
129 case 9: /* FillOrMix_1 */
130 mask = 0x03;
131 opcode = 0x02;
132 fom_mask = 3;
133 break;
134 case 0x0a: /* FillOrMix_2 */
135 mask = 0x05;
136 opcode = 0x02;
137 fom_mask = 5;
138 break;
139
140 }
141
142 lastopcode = opcode;
143 mixmask = 0;
144
145 /* Output body */
146 while (count > 0)
147 {
148 if (x >= width)
149 {
150 if (height <= 0)
151 return False;
152
153 x = 0;
154 height--;
155
156 prevline = line;
157 line = output + height * width;
158 }
159
160 switch (opcode)
161 {
162 case 0: /* Fill */
163 if (insertmix)
164 {
165 if (prevline == NULL)
166 line[x] = mix;
167 else
168 line[x] = prevline[x] ^ mix;
169
170 insertmix = False;
171 count--;
172 x++;
173 }
174
175 if (prevline == NULL)
176 {
177 REPEAT(line[x] = 0);
178 }
179 else
180 {
181 REPEAT(line[x] = prevline[x]);
182 }
183 break;
184
185 case 1: /* Mix */
186 if (prevline == NULL)
187 {
188 REPEAT(line[x] = mix);
189 }
190 else
191 {
192 REPEAT(line[x] = prevline[x] ^ mix);
193 }
194 break;
195
196 case 2: /* Fill or Mix */
197 if (prevline == NULL)
198 {
199 REPEAT(MASK_UPDATE();
200 if (mask & mixmask) line[x] = mix;
201 else
202 line[x] = 0;);
203 }
204 else
205 {
206 REPEAT(MASK_UPDATE();
207 if (mask & mixmask)
208 line[x] = prevline[x] ^ mix;
209 else
210 line[x] = prevline[x];);
211 }
212 break;
213
214 case 3: /* Colour */
215 REPEAT(line[x] = colour2);
216 break;
217
218 case 4: /* Copy */
219 REPEAT(line[x] = CVAL(input));
220 break;
221
222 case 8: /* Bicolour */
223 REPEAT(if (bicolour)
224 {
225 line[x] = colour2; bicolour = False;}
226 else
227 {
228 line[x] = colour1; bicolour = True; count++;}
229 );
230 break;
231
232 case 0xd: /* White */
233 REPEAT(line[x] = 0xff);
234 break;
235
236 case 0xe: /* Black */
237 REPEAT(line[x] = 0x00);
238 break;
239
240 default:
241 unimpl("bitmap opcode 0x%x\n", opcode);
242 return False;
243 }
244 }
245 }
246
247 return True;
248 }

  ViewVC Help
Powered by ViewVC 1.1.26