/[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 314 by jsorg71, Fri Feb 7 23:43:37 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  #include <fcntl.h>  
23    #define CVAL(p)   (*(p++))
24    
25    uint32 cvalx(unsigned char **input, int Bpp)
26    {
27            uint32 rv = 0;
28            memcpy(&rv, *input, Bpp);
29            *input += Bpp;
30            return rv;
31    }
32    
33    void setli(unsigned char * input, int offset, uint32 value, int Bpp)
34    {
35            input += offset * Bpp;
36            memcpy(input, &value, Bpp);
37    }
38    
39    uint32 getli(unsigned char * input, int offset, int Bpp)
40    {
41            uint32 rv = 0;
42            input += offset * Bpp;
43            memcpy(&rv, input, Bpp);
44            return rv;
45    }
46    
47  #define BITMAP_DEBUG 1  #define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
48    
49  #if BITMAP_DEBUG  #define REPEAT(statement) \
50  void hexdump(char *filename, unsigned char *data, int length);  { \
51  #endif          while((count & ~0x7) && ((x+8) < width)) \
52                    UNROLL8( statement; count--; x++; ); \
53  #define RCVAL()   (*(input++))          \
54  #define RSVAL()   ((*((input++) + 1) << 8) | RCVAL())          while((count > 0) && (x < width)) { statement; count--; x++; } \
55  #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); }}  
56    
57  BOOL bitmap_decompress(unsigned char *input, int size,  #define MASK_UPDATE() \
58                         unsigned char *output, int width)  { \
59            mixmask <<= 1; \
60            if (mixmask == 0) \
61            { \
62                    mask = fom_mask ? fom_mask : CVAL(input); \
63                    mixmask = 1; \
64            } \
65    }
66    
67    BOOL
68    bitmap_decompress(unsigned char *output, int width, int height, unsigned char *input, int size, int Bpp)
69  {  {
         unsigned char *savedinput = input;  
         unsigned char *start = output;  
70          unsigned char *end = input + size;          unsigned char *end = input + size;
71          unsigned char code;          unsigned char *prevline = NULL, *line = NULL;
72          unsigned char mix = 0xFF;          int opcode, count, offset, isfillormix, x = width;
73          int n, savedn;          int lastopcode = -1, insertmix = False, bicolour = False;
74            uint8 code;
75            uint32 colour1 = 0, colour2 = 0;
76            uint8 mixmask, mask = 0;
77            uint32 mix = 0xffffffff;
78            int fom_mask = 0;
79    
80          while (input < end)          while (input < end)
81          {          {
82                  code = RCVAL();                  fom_mask = 0;
83                  switch (code)                  code = CVAL(input);
84                    opcode = code >> 4;
85    
86                    /* Handle different opcode forms */
87                    switch (opcode)
88                    {
89                            case 0xc:
90                            case 0xd:
91                            case 0xe:
92                                    opcode -= 6;
93                                    count = code & 0xf;
94                                    offset = 16;
95                                    break;
96    
97                            case 0xf:
98                                    opcode = code & 0xf;
99                                    if (opcode < 9)
100                                    {
101                                            count = CVAL(input);
102                                            count |= CVAL(input) << 8;
103                                    }
104                                    else
105                                    {
106                                            count = (opcode < 0xb) ? 8 : 1;
107                                    }
108                                    offset = 0;
109                                    break;
110    
111                            default:
112                                    opcode >>= 1;
113                                    count = code & 0x1f;
114                                    offset = 32;
115                                    break;
116                    }
117    
118                    /* Handle strange cases for counts */
119                    if (offset != 0)
120                  {                  {
121                  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;  
122    
123                          if (n == 0)                          if (count == 0)
124                          {                          {
125                                  fprintf(stderr, "Undefined escape 0x%X\n", code);                                  if (isfillormix)
126                                  return False;                                          count = CVAL(input) + 1;
127                                    else
128                                            count = CVAL(input) + offset;
129                          }                          }
130                            else if (isfillormix)
                         switch ((code >> 5) & 7)  
131                          {                          {
132                          case 0: // Fill                                  count <<= 3;
133                                  FILL();                          }
134                                  break;                  }
135                          case 1: // Mix  
136                                  MIX();                  /* Read preliminary data */
137                    switch (opcode)
138                    {
139                            case 0: /* Fill */
140                                    if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
141                                            insertmix = True;
142                                  break;                                  break;
143                          case 2: // FillOrMix                          case 8: /* Bicolour */
144                                  fprintf(stderr, "FillOrMix unsupported\n");                                  colour1 = cvalx(&input, Bpp);
145                                  n *= 8;                          case 3: /* Colour */
146                                  savedn = n;                                  colour2 = cvalx(&input, Bpp);
                                 MIX();  
                                 input += (savedn+7)/8;  
147                                  break;                                  break;
148                          case 3: // Color                          case 6: /* SetMix/Mix */
149                                  COLOR();                          case 7: /* SetMix/FillOrMix */
150                                    mix = cvalx(&input, Bpp);
151                                    opcode -= 5;
152                                  break;                                  break;
153                          case 4: // Copy                          case 9: /* FillOrMix_1 */
154                                  COPY();                                  mask = 0x03;
155                                    opcode = 0x02;
156                                    fom_mask = 3;
157                                  break;                                  break;
158                          case 5: // Copy Packed                          case 0x0a:      /* FillOrMix_2 */
159                                  fprintf(stderr, "CopyPacked 3\n");                                  mask = 0x05;
160                                  COPY_PACKED();                                  opcode = 0x02;
161                                    fom_mask = 5;
162                                  break;                                  break;
                         case 6:  
                                 n = code & 15;  
163    
164                                  switch ((code >> 4) & 15)                  }
165                                  {  
166                                  case 0xC:                  lastopcode = opcode;
167                                          fprintf(stderr, "SetMix_Mix 3\n");                  mixmask = 0;
168                                          SETMIX_MIX();  
169                                          break;                  /* Output body */
170                                  case 0xD:                  while (count > 0)
171                                          fprintf(stderr, "SetMix_FillOrMix unsupported\n");                  {
172                                          n *= 8;                          if (x >= width)
173                                          savedn = n;                          {
174                                          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);  
175                                          return False;                                          return False;
176                                  }  
177                                    x = 0;
178                                    height--;
179    
180                                    prevline = line;
181                                    line = output + height * width * Bpp;
182                          }                          }
                 }  
         }  
183    
184          printf("Uncompressed size: %d\n", output - start);                          switch (opcode)
185  #if BITMAP_DEBUG                          {
186          {                                  case 0: /* Fill */
187                  static int bmpno = 1;                                          if (insertmix)
188                  char filename[64];                                          {
189                                                    if (prevline == NULL)
190                                                            setli(line, x, mix, Bpp);
191                                                    else
192                                                            setli(line, x, getli(prevline, x, Bpp) ^ mix, Bpp);
193    
194                                                    insertmix = False;
195                                                    count--;
196                                                    x++;
197                                            }
198    
199                                            if (prevline == NULL)
200                                            {
201                                                    REPEAT(setli(line, x, 0, Bpp))
202                                            }
203                                            else
204                                            {
205                                                    REPEAT(setli(line, x, getli(prevline, x, Bpp), Bpp));
206                                            }
207                                            break;
208    
209                  snprintf(filename, sizeof(filename)-1, "in%d.raw", bmpno);                                  case 1: /* Mix */
210                  hexdump(filename, savedinput, size);                                          if (prevline == NULL)
211                                            {
212                                                    REPEAT(setli(line, x, mix, Bpp));
213                                            }
214                                            else
215                                            {
216                                                    REPEAT(setli(line, x, getli(prevline, x, Bpp) ^ mix, Bpp));
217                                            }
218                                            break;
219    
220                  snprintf(filename, sizeof(filename)-1, "out%d.raw", bmpno);                                  case 2: /* Fill or Mix */
221                  hexdump(filename, start, output-start);                                          if (prevline == NULL)
222                                            {
223                                                    REPEAT(MASK_UPDATE();
224                                                           if (mask & mixmask) setli(line, x, mix, Bpp);
225                                                           else
226                                                           setli(line, x, 0, Bpp););
227                                            }
228                                            else
229                                            {
230                                                    REPEAT(MASK_UPDATE();
231                                                           if (mask & mixmask)
232                                                           setli(line, x, getli(prevline, x, Bpp) ^ mix, Bpp);
233                                                           else
234                                                           setli(line, x, getli(prevline, x, Bpp), Bpp););
235                                            }
236                                            break;
237    
238                  bmpno++;                                  case 3: /* Colour */
239          }                                          REPEAT(setli(line, x, colour2, Bpp));
240  #endif                                          break;
241    
242          return True;                                  case 4: /* Copy */
243  }                                          REPEAT(setli(line, x, cvalx(&input, Bpp), Bpp));
244                                            break;
245    
246                                    case 8: /* Bicolour */
247                                            REPEAT(if (bicolour)
248                                                   {
249                                                   setli(line, x, colour2, Bpp); bicolour = False;}
250                                                   else
251                                                   {
252                                                   setli(line, x, colour1, Bpp); bicolour = True; count++;}
253                                            );
254                                            break;
255    
256  #if BITMAP_DEBUG                                  case 0xd:       /* White */
257  void hexdump(char *filename, unsigned char *data, int length)                                          REPEAT(setli(line, x, 0xffffffff, Bpp));
258  {                                          break;
         /*  
         int i;  
259    
260          for (i = 0; i < length; i++)                                  case 0xe:       /* Black */
261          {                                          REPEAT(setli(line, x, 0, Bpp));
262                  printf("%02X ", data[i]);                                          break;
263    
264                  if (i % 16 == 15)                                  default:
265                          printf("\n");                                          unimpl("bitmap opcode 0x%x\n", opcode);
266                                            return False;
267                            }
268                    }
269          }          }
         */  
   
         int fd;  
270    
271          fd = open(filename, O_WRONLY|O_CREAT, 0600);          return True;
         write(fd, data, length);  
         close(fd);  
272  }  }
273  #endif  

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

  ViewVC Help
Powered by ViewVC 1.1.26