/[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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 9 by matty, Tue Jul 25 12:34:29 2000 UTC revision 309 by jsorg71, Tue Feb 4 05:32:13 2003 UTC
# Line 1  Line 1 
1  /*  /*
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Bitmap decompression routines     Bitmap decompression routines
4     Copyright (C) Matthew Chapman 1999-2000     Copyright (C) Matthew Chapman 1999-2002
5      
6     This program is free software; you can redistribute it and/or modify     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     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     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
21  #include "includes.h"  #include "rdesktop.h"
22    
23  #define CVAL(p)   (*(p++))  #define CVAL(p)   (*(p++))
24  #define SVAL(p)   ((*((p++) + 1) << 8) | CVAL(p))  #define CVAL16(p) (*(((uint16*)p)++))
25    
26  #define REPEAT(statement) { while ((count > 0) && (x < width)) { statement; count--; x++; } }  #define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
 #define MASK_UPDATE() { mixmask <<= 1; if (mixmask == 0) { mask = CVAL(input); mixmask = 1; } }  
27    
28  BOOL bitmap_decompress(unsigned char *output, int width, int height,  #define REPEAT(statement) \
29                         unsigned char *input, int size)  { \
30            while((count & ~0x7) && ((x+8) < width)) \
31                    UNROLL8( statement; count--; x++; ); \
32            \
33            while((count > 0) && (x < width)) { statement; count--; x++; } \
34    }
35    
36    #define MASK_UPDATE() \
37    { \
38            mixmask <<= 1; \
39            if (mixmask == 0) \
40            { \
41                    mask = fom_mask ? fom_mask : CVAL(input); \
42                    mixmask = 1; \
43            } \
44    }
45    
46    BOOL
47    bitmap_decompress8(unsigned char *output, int width, int height, unsigned char *input, int size)
48  {  {
49          unsigned char *end = input + size;          unsigned char *end = input + size;
50          unsigned char *prevline, *line = NULL;          unsigned char *prevline = NULL, *line = NULL;
51          int opcode, count, offset, isfillormix, x = width;          int opcode, count, offset, isfillormix, x = width;
52          int lastopcode = -1, insertmix = False;          int lastopcode = -1, insertmix = False, bicolour = False;
53          uint8 code, colour1, colour2, mask, mixmask;          uint8 code, colour1 = 0, colour2 = 0;
54          uint8 mix = 0xff;          uint8 mixmask, mask = 0, mix = 0xff;
55            int fom_mask = 0;
56    
57          while (input < end)          while (input < end)
58          {          {
59                    fom_mask = 0;
60                  code = CVAL(input);                  code = CVAL(input);
61                  opcode = code >> 4;                  opcode = code >> 4;
62    
# Line 54  BOOL bitmap_decompress(unsigned char *ou Line 73  BOOL bitmap_decompress(unsigned char *ou
73    
74                          case 0xf:                          case 0xf:
75                                  opcode = code & 0xf;                                  opcode = code & 0xf;
76                                  count = (opcode < 13) ? SVAL(input) : 1;                                  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;                                  offset = 0;
86                                  break;                                  break;
87    
# Line 84  BOOL bitmap_decompress(unsigned char *ou Line 111  BOOL bitmap_decompress(unsigned char *ou
111                  }                  }
112    
113                  /* Read preliminary data */                  /* Read preliminary data */
                 mixmask = 0;  
114                  switch (opcode)                  switch (opcode)
115                  {                  {
116                          case 0: /* Fill */                          case 0: /* Fill */
117                                  if ((lastopcode == opcode) && (x != width))                                  if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
118                                          insertmix = True;                                          insertmix = True;
119                                  break;                                  break;
120                          case 8: /* Bicolour */                          case 8: /* Bicolour */
121                                  colour1 = CVAL(input);                                  colour1 = CVAL(input);
122                          case 3: /* Colour */                          case 3: /* Colour */
123                                  colour2 = CVAL(input);                                  colour2 = CVAL(input);
124                                  break;                                  break;
125                          case 6: /* SetMix/Mix */                          case 6: /* SetMix/Mix */
126                          case 7: /* SetMix/FillOrMix */                          case 7: /* SetMix/FillOrMix */
127                                  mix = CVAL(input);                                  mix = CVAL(input);
128                                  opcode -= 5;                                  opcode -= 5;
129                                  break;                                  break;
130                            case 9: /* FillOrMix_1 */
131                                    mask = 0x03;
132                                    opcode = 0x02;
133                                    fom_mask = 3;
134                                    break;
135                            case 0x0a:      /* FillOrMix_2 */
136                                    mask = 0x05;
137                                    opcode = 0x02;
138                                    fom_mask = 5;
139                                    break;
140    
141                  }                  }
142    
143                  lastopcode = opcode;                  lastopcode = opcode;
144                    mixmask = 0;
145    
146                  /* Output body */                  /* Output body */
147                  while (count > 0)                  while (count > 0)
# Line 121  BOOL bitmap_decompress(unsigned char *ou Line 160  BOOL bitmap_decompress(unsigned char *ou
160    
161                          switch (opcode)                          switch (opcode)
162                          {                          {
163                                  case 0: /* Fill */                                  case 0: /* Fill */
164                                          if (insertmix)                                          if (insertmix)
165                                          {                                          {
166                                                  if (prevline == NULL)                                                  if (prevline == NULL)
# Line 135  BOOL bitmap_decompress(unsigned char *ou Line 174  BOOL bitmap_decompress(unsigned char *ou
174                                          }                                          }
175    
176                                          if (prevline == NULL)                                          if (prevline == NULL)
177                                                  REPEAT(line[x] = 0)                                          {
178                                                    REPEAT(line[x] = 0);
179                                            }
180                                          else                                          else
181                                                  REPEAT(line[x] = prevline[x])                                          {
182                                                    REPEAT(line[x] = prevline[x]);
183                                            }
184                                          break;                                          break;
185    
186                                  case 1: /* Mix */                                  case 1: /* Mix */
187                                          if (prevline == NULL)                                          if (prevline == NULL)
188                                                  REPEAT(line[x] = mix)                                          {
189                                                    REPEAT(line[x] = mix);
190                                            }
191                                          else                                          else
192                                                  REPEAT(line[x] = prevline[x] ^ mix)                                          {
193                                                    REPEAT(line[x] = prevline[x] ^ mix);
194                                            }
195                                          break;                                          break;
196    
197                                  case 2: /* Fill or Mix */                                  case 2: /* Fill or Mix */
198                                          if (prevline == NULL)                                          if (prevline == NULL)
199                                              REPEAT(                                          {
200                                                     MASK_UPDATE();                                                  REPEAT(MASK_UPDATE();
201                                                           if (mask & mixmask) line[x] = mix;
202                                                           else
203                                                           line[x] = 0;);
204                                            }
205                                            else
206                                            {
207                                                    REPEAT(MASK_UPDATE();
208                                                           if (mask & mixmask)
209                                                           line[x] = prevline[x] ^ mix;
210                                                           else
211                                                           line[x] = prevline[x];);
212                                            }
213                                            break;
214    
215                                    case 3: /* Colour */
216                                            REPEAT(line[x] = colour2);
217                                            break;
218    
219                                    case 4: /* Copy */
220                                            REPEAT(line[x] = CVAL(input));
221                                            break;
222    
223                                                     if (mask & mixmask)                                  case 8: /* Bicolour */
224                                            REPEAT(if (bicolour)
225                                                   {
226                                                   line[x] = colour2; bicolour = False;}
227                                                   else
228                                                   {
229                                                   line[x] = colour1; bicolour = True; count++;}
230                                            );
231                                            break;
232    
233                                    case 0xd:       /* White */
234                                            REPEAT(line[x] = 0xff);
235                                            break;
236    
237                                    case 0xe:       /* Black */
238                                            REPEAT(line[x] = 0x00);
239                                            break;
240    
241                                    default:
242                                            unimpl("bitmap opcode 0x%x\n", opcode);
243                                            return False;
244                            }
245                    }
246            }
247    
248            return True;
249    }
250    
251    BOOL
252    bitmap_decompress16(unsigned char *output, int width, int height, unsigned char *input, int size)
253    {
254            unsigned char *end = input + size;
255            uint16 *prevline = NULL, *line = NULL;
256            int opcode, count, offset, isfillormix, x = width;
257            int lastopcode = -1, insertmix = False, bicolour = False;
258            uint8 code;
259            uint16 colour1 = 0, colour2 = 0;
260            uint8 mixmask, mask = 0;
261            uint16 mix = 0xffff;
262            int fom_mask = 0;
263    
264            while (input < end)
265            {
266                    fom_mask = 0;
267                    code = CVAL(input);
268                    opcode = code >> 4;
269    
270                    /* Handle different opcode forms */
271                    switch (opcode)
272                    {
273                            case 0xc:
274                            case 0xd:
275                            case 0xe:
276                                    opcode -= 6;
277                                    count = code & 0xf;
278                                    offset = 16;
279                                    break;
280    
281                            case 0xf:
282                                    opcode = code & 0xf;
283                                    if (opcode < 9)
284                                    {
285                                            count = CVAL(input);
286                                            count |= CVAL(input) << 8;
287                                    }
288                                    else
289                                    {
290                                            count = (opcode < 0xd) ? 8 : 1; // was 0xb in 8 bit
291                                    }
292                                    offset = 0;
293                                    break;
294    
295                            default:
296                                    opcode >>= 1;
297                                    count = code & 0x1f;
298                                    offset = 32;
299                                    break;
300                    }
301    
302                    /* Handle strange cases for counts */
303                    if (offset != 0)
304                    {
305                            isfillormix = ((opcode == 2) || (opcode == 7));
306    
307                            if (count == 0)
308                            {
309                                    if (isfillormix)
310                                            count = CVAL(input) + 1;
311                                    else
312                                            count = CVAL(input) + offset;
313                            }
314                            else if (isfillormix)
315                            {
316                                    count <<= 3;
317                            }
318                    }
319    
320                    /* Read preliminary data */
321                    switch (opcode)
322                    {
323                            case 0: /* Fill */
324                                    if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
325                                            insertmix = True;
326                                    break;
327                            case 8: /* Bicolour */
328                                    colour1 = CVAL16(input);
329                            case 3: /* Colour */
330                                    colour2 = CVAL16(input);
331                                    break;
332                            case 6: /* SetMix/Mix */
333                            case 7: /* SetMix/FillOrMix */
334                                    mix = CVAL16(input);
335                                    opcode -= 5;
336                                    break;
337                            case 9: /* FillOrMix_1 */
338                                    mask = 0x03;
339                                    opcode = 0x02;
340                                    fom_mask = 3;
341                                    break;
342                            case 0x0a:      /* FillOrMix_2 */
343                                    mask = 0x05;
344                                    opcode = 0x02;
345                                    fom_mask = 5;
346                                    break;
347    
348                    }
349    
350                    lastopcode = opcode;
351                    mixmask = 0;
352    
353                    /* Output body */
354                    while (count > 0)
355                    {
356                            if (x >= width)
357                            {
358                                    if (height <= 0)
359                                            return False;
360    
361                                    x = 0;
362                                    height--;
363    
364                                    prevline = line;
365                                    line = (uint16*)output + height * width;
366                            }
367    
368                            switch (opcode)
369                            {
370                                    case 0: /* Fill */
371                                            if (insertmix)
372                                            {
373                                                    if (prevline == NULL)
374                                                          line[x] = mix;                                                          line[x] = mix;
375                                                     else                                                  else
376                                                          line[x] = 0;                                                          line[x] = prevline[x] ^ mix;
377                                              )  
378                                                    insertmix = False;
379                                                    count--;
380                                                    x++;
381                                            }
382    
383                                            if (prevline == NULL)
384                                            {
385                                                    REPEAT(line[x] = 0);
386                                            }
387                                          else                                          else
388                                              REPEAT(                                          {
389                                                     MASK_UPDATE();                                                  REPEAT(line[x] = prevline[x]);
390                                            }
391                                            break;
392    
393                                                     if (mask & mixmask)                                  case 1: /* Mix */
394                                                          line[x] = prevline[x] ^ mix;                                          if (prevline == NULL)
395                                                     else                                          {
396                                                          line[x] = prevline[x];                                                  REPEAT(line[x] = mix);
397                                              )                                          }
398                                            else
399                                            {
400                                                    REPEAT(line[x] = prevline[x] ^ mix);
401                                            }
402                                            break;
403    
404                                    case 2: /* Fill or Mix */
405                                            if (prevline == NULL)
406                                            {
407                                                    REPEAT(MASK_UPDATE();
408                                                           if (mask & mixmask) line[x] = mix;
409                                                           else
410                                                           line[x] = 0;);
411                                            }
412                                            else
413                                            {
414                                                    REPEAT(MASK_UPDATE();
415                                                           if (mask & mixmask)
416                                                           line[x] = prevline[x] ^ mix;
417                                                           else
418                                                           line[x] = prevline[x];);
419                                            }
420                                          break;                                          break;
421    
422                                  case 3: /* Colour */                                  case 3: /* Colour */
423                                          REPEAT(line[x] = colour2)                                          REPEAT(line[x] = colour2);
424                                          break;                                          break;
425    
426                                  case 4: /* Copy */                                  case 4: /* Copy */
427                                          REPEAT(line[x] = CVAL(input))                                          REPEAT(line[x] = CVAL16(input));
428                                          break;                                          break;
429    
430                                  case 8: /* Bicolour */                                  case 8: /* Bicolour */
431                                          REPEAT(line[x] = colour1; line[++x] = colour2)                                          REPEAT(if (bicolour)
432                                                   {
433                                                   line[x] = colour2; bicolour = False;}
434                                                   else
435                                                   {
436                                                   line[x] = colour1; bicolour = True; count++;}
437                                            );
438                                          break;                                          break;
439    
440                                  case 13: /* White */                                  case 0xd:       /* White */
441                                          REPEAT(line[x] = 0xff)                                          REPEAT(line[x] = 0xffff);
442                                          break;                                          break;
443    
444                                  case 14: /* Black */                                  case 0xe:       /* Black */
445                                          REPEAT(line[x] = 0x00)                                          REPEAT(line[x] = 0x00);
446                                          break;                                          break;
447    
448                                  default:                                  default:
449                                          NOTIMP("bitmap opcode 0x%x\n", opcode);                                          unimpl("bitmap opcode 0x%x\n", opcode);
450                                          return False;                                          return False;
451                          }                          }
452                  }                  }
# Line 197  BOOL bitmap_decompress(unsigned char *ou Line 454  BOOL bitmap_decompress(unsigned char *ou
454    
455          return True;          return True;
456  }  }
457    
458    BOOL
459    bitmap_decompress(unsigned char *output, int width, int height, unsigned char *input, int size, int bpp)
460    {
461            if (bpp == 8)
462                    return bitmap_decompress8(output, width, height, input, size);
463            else if (bpp == 16)
464                    return bitmap_decompress16(output, width, height, input, size);
465            else
466                    return False;
467    }

Legend:
Removed from v.9  
changed lines
  Added in v.309

  ViewVC Help
Powered by ViewVC 1.1.26