/[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 4 by matty, Wed May 10 07:36:34 2000 UTC revision 207 by matthewc, Thu Sep 26 14:26:46 2002 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
# Line 18  Line 18 
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"
 #include <fcntl.h>  
22    
23  #define BITMAP_DEBUG 1  #define CVAL(p)   (*(p++))
24    
25  #if BITMAP_DEBUG  #define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
 void hexdump(char *filename, unsigned char *data, int length);  
 #endif  
   
 #define RCVAL()   (*(input++))  
 #define RSVAL()   ((*((input++) + 1) << 8) | RCVAL())  
 #define SCVAL(v)  {*(output++) = (v);}  
   
 #define FILL()    {while (n-- > 0) { if (output - start < width) { SCVAL(0) } else { SCVAL(*(output-width)); }}}  
 #define MIX()     {while (n-- > 0) { if (output - start < width) { SCVAL(mix) } else { SCVAL(*(output-width) ^ mix); }}}  
 #define COPY()    {while (n-- > 0) { SCVAL(RCVAL()); }}  
 #define COLOR()   {int color = RCVAL(); \  
                    while (n-- > 0) { SCVAL(color); }}  
 #define BICOLOR() {int color1 = RCVAL(); int color2 = RCVAL(); \  
                    while (n-- > 0) { SCVAL(color1); SCVAL(color2); }}  
 #define SETMIX_MIX() {mix = RCVAL(); MIX();}  
 #define COPY_PACKED() {n++; n/=2; while (n-- > 0) \  
                       {unsigned char c = RCVAL(); SCVAL((c & 0xF0) >> 4); \  
                                                   SCVAL(c & 0x0F); }}  
26    
27  BOOL bitmap_decompress(unsigned char *input, int size,  #define REPEAT(statement) \
28                         unsigned char *output, int width)  { \
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  {  {
         unsigned char *savedinput = input;  
         unsigned char *start = output;  
48          unsigned char *end = input + size;          unsigned char *end = input + size;
49          unsigned char code;          unsigned char *prevline = NULL, *line = NULL;
50          unsigned char mix = 0xFF;          int opcode, count, offset, isfillormix, x = width;
51          int n, savedn;          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)          while (input < end)
57          {          {
58                  code = RCVAL();                  fom_mask = 0;
59                  switch (code)                  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                  case 0x00: // Fill                          isfillormix = ((opcode == 2) || (opcode == 7));
                         n = RCVAL() + 32;  
                         FILL();  
                         break;  
                 case 0xF0: // Fill  
                         n = RSVAL();  
                         FILL();  
                         break;  
                 case 0x20: // Mix  
                         n = RCVAL() + 32;  
                         MIX();  
                         break;  
                 case 0xF1: // Mix  
                         n = RSVAL();  
                         MIX();  
                         break;  
                 case 0x40: // FillOrMix  
                         fprintf(stderr, "FillOrMix unsupported\n");  
                         savedn = n = RCVAL() + 1;  
                         MIX();  
                         input += (savedn+7)/8;  
                         break;  
                 case 0xF2:  
                         fprintf(stderr, "FillOrMix unsupported\n");  
                         savedn = n = RSVAL();  
                         MIX();  
                         input += (savedn+7)/8;  
                         break;  
                 case 0x60: // Color  
                         n = RCVAL() + 32;  
                         COLOR();  
                         break;  
                 case 0xF3:  
                         n = RSVAL();  
                         fprintf(stderr, "Color %d\n", n);  
                         COLOR();  
                         break;  
                 case 0x80: // Copy  
                         n = RCVAL() + 32;  
                         COPY();  
                         break;  
                 case 0xF4:  
                         n = RSVAL();  
                         COPY();  
                         break;  
                 case 0xA0: // Copy Packed  
                         fprintf(stderr, "CopyPacked 1\n");  
                         n = RCVAL() + 32;  
                         COPY_PACKED();  
                         break;  
                 case 0xF5:  
                         fprintf(stderr, "CopyPacked 2\n");  
                         n = RSVAL();  
                         COPY_PACKED();  
                         break;  
                 case 0xC0: // SetMix_Mix  
                         fprintf(stderr, "SetMix_Mix 1\n");  
                         n = RCVAL() + 16;  
                         SETMIX_MIX();  
                         break;  
                 case 0xF6:  
                         fprintf(stderr, "SetMix_Mix 2\n");  
                         n = RSVAL();  
                         SETMIX_MIX();  
                         break;  
                 case 0xD0: // SetMix_FillOrMix  
                         fprintf(stderr, "SetMix_FillOrMix unsupported\n");  
                         savedn = n = RCVAL() + 1;  
                         SETMIX_MIX();  
                         input += (savedn+7)/8;  
                         break;  
                 case 0xF7:  
                         fprintf(stderr, "SetMix_FillOrMix unsupported\n");  
                         savedn = n = RSVAL();  
                         SETMIX_MIX();  
                         input += (savedn+7)/8;  
                         break;  
                 case 0xE0: // Bicolor  
                         fprintf(stderr, "Bicolor 1\n");  
                         n = RCVAL() + 16;  
                         BICOLOR();  
                         break;  
                 case 0xF8:  
                         fprintf(stderr, "Bicolor 2\n");  
                         n = RSVAL();  
                         BICOLOR();  
                         break;  
                 case 0xF9: // FillOrMix_1  
                         fprintf(stderr, "FillOrMix_1 unsupported\n");  
                         return False;  
                 case 0xFA: // FillOrMix_2  
                         fprintf(stderr, "FillOrMix_2 unsupported\n");  
                         return False;  
                 case 0xFD: // White  
                         SCVAL(0xFF);  
                         break;  
                 case 0xFE: // Black  
                         SCVAL(0);  
                         break;  
                 default:  
                         n = code & 31;  
98    
99                          if (n == 0)                          if (count == 0)
100                          {                          {
101                                  fprintf(stderr, "Undefined escape 0x%X\n", code);                                  if (isfillormix)
102                                  return False;                                          count = CVAL(input) + 1;
103                                    else
104                                            count = CVAL(input) + offset;
105                          }                          }
106                            else if (isfillormix)
                         switch ((code >> 5) & 7)  
107                          {                          {
108                          case 0: // Fill                                  count <<= 3;
109                                  FILL();                          }
110                                  break;                  }
111                          case 1: // Mix  
112                                  MIX();                  /* Read preliminary data */
113                                  break;                  switch (opcode)
114                          case 2: // FillOrMix                  {
115                                  fprintf(stderr, "FillOrMix unsupported\n");                          case 0: /* Fill */
116                                  n *= 8;                                  if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
117                                  savedn = n;                                          insertmix = True;
118                                  MIX();                                  break;
119                                  input += (savedn+7)/8;                          case 8: /* Bicolour */
120                                  break;                                  colour1 = CVAL(input);
121                          case 3: // Color                          case 3: /* Colour */
122                                  COLOR();                                  colour2 = CVAL(input);
123                                  break;                                  break;
124                          case 4: // Copy                          case 6: /* SetMix/Mix */
125                                  COPY();                          case 7: /* SetMix/FillOrMix */
126                                  break;                                  mix = CVAL(input);
127                          case 5: // Copy Packed                                  opcode -= 5;
128                                  fprintf(stderr, "CopyPacked 3\n");                                  break;
129                                  COPY_PACKED();                          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;                                  break;
                         case 6:  
                                 n = code & 15;  
139    
140                                  switch ((code >> 4) & 15)                  }
141                                  {  
142                                  case 0xC:                  lastopcode = opcode;
143                                          fprintf(stderr, "SetMix_Mix 3\n");                  mixmask = 0;
144                                          SETMIX_MIX();  
145                                          break;                  /* Output body */
146                                  case 0xD:                  while (count > 0)
147                                          fprintf(stderr, "SetMix_FillOrMix unsupported\n");                  {
148                                          n *= 8;                          if (x >= width)
149                                          savedn = n;                          {
150                                          SETMIX_MIX();                                  if (height <= 0)
                                         input += (savedn+7)/8;  
                                         break;  
                                 case 0xE:  
                                         fprintf(stderr, "Bicolor 3\n");  
                                         BICOLOR();  
                                         break;  
                                 default:  
                                         fprintf(stderr, "Undefined escape 0x%X\n", code);  
151                                          return False;                                          return False;
152                                  }  
153                                    x = 0;
154                                    height--;
155    
156                                    prevline = line;
157                                    line = output + height * width;
158                          }                          }
                 }  
         }  
159    
160          printf("Uncompressed size: %d\n", output - start);                          switch (opcode)
161  #if BITMAP_DEBUG                          {
162          {                                  case 0: /* Fill */
163                  static int bmpno = 1;                                          if (insertmix)
164                  char filename[64];                                          {
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                  snprintf(filename, sizeof(filename)-1, "in%d.raw", bmpno);                                  case 1: /* Mix */
186                  hexdump(filename, savedinput, size);                                          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                  snprintf(filename, sizeof(filename)-1, "out%d.raw", bmpno);                                  case 2: /* Fill or Mix */
197                  hexdump(filename, start, output-start);                                          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                  bmpno++;                                  case 3: /* Colour */
215          }                                          REPEAT(line[x] = colour2);
216  #endif                                          break;
217    
218          return True;                                  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  #if BITMAP_DEBUG                                  case 0xd:       /* White */
233  void hexdump(char *filename, unsigned char *data, int length)                                          REPEAT(line[x] = 0xff);
234  {                                          break;
         /*  
         int i;  
235    
236          for (i = 0; i < length; i++)                                  case 0xe:       /* Black */
237          {                                          REPEAT(line[x] = 0x00);
238                  printf("%02X ", data[i]);                                          break;
239    
240                  if (i % 16 == 15)                                  default:
241                          printf("\n");                                          unimpl("bitmap opcode 0x%x\n", opcode);
242                                            return False;
243                            }
244                    }
245          }          }
         */  
   
         int fd;  
246    
247          fd = open(filename, O_WRONLY|O_CREAT, 0600);          return True;
         write(fd, data, length);  
         close(fd);  
248  }  }
 #endif  

Legend:
Removed from v.4  
changed lines
  Added in v.207

  ViewVC Help
Powered by ViewVC 1.1.26