/[rdesktop]/sourceforge.net/tags/RDESKTOP-1-3-1/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/tags/RDESKTOP-1-3-1/rdesktop/bitmap.c

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

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

Legend:
Removed from v.3  
changed lines
  Added in v.345

  ViewVC Help
Powered by ViewVC 1.1.26