/[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 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  #include <fcntl.h>  
23    #define CVAL(p)   (*(p++))
24    #define CVAL16(p) (*(((uint16*)p)++))
25    
26  #define BITMAP_DEBUG 1  #define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
27    
28  #if BITMAP_DEBUG  #define REPEAT(statement) \
29  void hexdump(char *filename, unsigned char *data, int length);  { \
30  #endif          while((count & ~0x7) && ((x+8) < width)) \
31                    UNROLL8( statement; count--; x++; ); \
32  #define RCVAL()   (*(input++))          \
33  #define RSVAL()   ((*((input++) + 1) << 8) | RCVAL())          while((count > 0) && (x < width)) { statement; count--; x++; } \
34  #define SCVAL(v)  {*(output++) = (v);}  }
35    
36  #define FILL()    {while (n-- > 0) { if (output - start < width) { SCVAL(0) } else { SCVAL(*(output-width)); }}}  #define MASK_UPDATE() \
37  #define MIX()     {while (n-- > 0) { if (output - start < width) { SCVAL(mix) } else { SCVAL(*(output-width) ^ mix); }}}  { \
38  #define COPY()    {while (n-- > 0) { SCVAL(RCVAL()); }}          mixmask <<= 1; \
39  #define COLOR()   {int color = RCVAL(); \          if (mixmask == 0) \
40                     while (n-- > 0) { SCVAL(color); }}          { \
41  #define BICOLOR() {int color1 = RCVAL(); int color2 = RCVAL(); \                  mask = fom_mask ? fom_mask : CVAL(input); \
42                     while (n-- > 0) { SCVAL(color1); SCVAL(color2); }}                  mixmask = 1; \
43  #define SETMIX_MIX() {mix = RCVAL(); MIX();}          } \
44  #define COPY_PACKED() {n++; n/=2; while (n-- > 0) \  }
                       {unsigned char c = RCVAL(); SCVAL((c & 0xF0) >> 4); \  
                                                   SCVAL(c & 0x0F); }}  
45    
46  BOOL bitmap_decompress(unsigned char *input, int size,  BOOL
47                         unsigned char *output, int width)  bitmap_decompress8(unsigned char *output, int width, int height, unsigned char *input, int size)
48  {  {
         unsigned char *savedinput = input;  
         unsigned char *start = output;  
49          unsigned char *end = input + size;          unsigned char *end = input + size;
50          unsigned char code;          unsigned char *prevline = NULL, *line = NULL;
51          unsigned char mix = 0xFF;          int opcode, count, offset, isfillormix, x = width;
52          int n, savedn;          int lastopcode = -1, insertmix = False, bicolour = False;
53            uint8 code, colour1 = 0, colour2 = 0;
54            uint8 mixmask, mask = 0, mix = 0xff;
55            int fom_mask = 0;
56    
57          while (input < end)          while (input < end)
58          {          {
59                  code = RCVAL();                  fom_mask = 0;
60                  switch (code)                  code = CVAL(input);
61                    opcode = code >> 4;
62    
63                    /* Handle different opcode forms */
64                    switch (opcode)
65                    {
66                            case 0xc:
67                            case 0xd:
68                            case 0xe:
69                                    opcode -= 6;
70                                    count = code & 0xf;
71                                    offset = 16;
72                                    break;
73    
74                            case 0xf:
75                                    opcode = code & 0xf;
76                                    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;
86                                    break;
87    
88                            default:
89                                    opcode >>= 1;
90                                    count = code & 0x1f;
91                                    offset = 32;
92                                    break;
93                    }
94    
95                    /* Handle strange cases for counts */
96                    if (offset != 0)
97                  {                  {
98                  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;  
99    
100                          if (n == 0)                          if (count == 0)
101                          {                          {
102                                  fprintf(stderr, "Undefined escape 0x%X\n", code);                                  if (isfillormix)
103                                  return False;                                          count = CVAL(input) + 1;
104                                    else
105                                            count = CVAL(input) + offset;
106                          }                          }
107                            else if (isfillormix)
                         switch ((code >> 5) & 7)  
108                          {                          {
109                          case 0: // Fill                                  count <<= 3;
110                                  FILL();                          }
111                                  break;                  }
112                          case 1: // Mix  
113                                  MIX();                  /* Read preliminary data */
114                    switch (opcode)
115                    {
116                            case 0: /* Fill */
117                                    if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
118                                            insertmix = True;
119                                  break;                                  break;
120                          case 2: // FillOrMix                          case 8: /* Bicolour */
121                                  fprintf(stderr, "FillOrMix unsupported\n");                                  colour1 = CVAL(input);
122                                  n *= 8;                          case 3: /* Colour */
123                                  savedn = n;                                  colour2 = CVAL(input);
                                 MIX();  
                                 input += (savedn+7)/8;  
124                                  break;                                  break;
125                          case 3: // Color                          case 6: /* SetMix/Mix */
126                                  COLOR();                          case 7: /* SetMix/FillOrMix */
127                                    mix = CVAL(input);
128                                    opcode -= 5;
129                                  break;                                  break;
130                          case 4: // Copy                          case 9: /* FillOrMix_1 */
131                                  COPY();                                  mask = 0x03;
132                                    opcode = 0x02;
133                                    fom_mask = 3;
134                                  break;                                  break;
135                          case 5: // Copy Packed                          case 0x0a:      /* FillOrMix_2 */
136                                  fprintf(stderr, "CopyPacked 3\n");                                  mask = 0x05;
137                                  COPY_PACKED();                                  opcode = 0x02;
138                                    fom_mask = 5;
139                                  break;                                  break;
                         case 6:  
                                 n = code & 15;  
140    
141                                  switch ((code >> 4) & 15)                  }
142                                  {  
143                                  case 0xC:                  lastopcode = opcode;
144                                          fprintf(stderr, "SetMix_Mix 3\n");                  mixmask = 0;
145                                          SETMIX_MIX();  
146                                          break;                  /* Output body */
147                                  case 0xD:                  while (count > 0)
148                                          fprintf(stderr, "SetMix_FillOrMix unsupported\n");                  {
149                                          n *= 8;                          if (x >= width)
150                                          savedn = n;                          {
151                                          SETMIX_MIX();                                  if (height <= 0)
152                                          input += (savedn+7)/8;                                          return False;
153                                          break;  
154                                  case 0xE:                                  x = 0;
155                                          fprintf(stderr, "Bicolor 3\n");                                  height--;
156                                          BICOLOR();  
157                                    prevline = line;
158                                    line = output + height * width;
159                            }
160    
161                            switch (opcode)
162                            {
163                                    case 0: /* Fill */
164                                            if (insertmix)
165                                            {
166                                                    if (prevline == NULL)
167                                                            line[x] = mix;
168                                                    else
169                                                            line[x] = prevline[x] ^ mix;
170    
171                                                    insertmix = False;
172                                                    count--;
173                                                    x++;
174                                            }
175    
176                                            if (prevline == NULL)
177                                            {
178                                                    REPEAT(line[x] = 0);
179                                            }
180                                            else
181                                            {
182                                                    REPEAT(line[x] = prevline[x]);
183                                            }
184                                            break;
185    
186                                    case 1: /* Mix */
187                                            if (prevline == NULL)
188                                            {
189                                                    REPEAT(line[x] = mix);
190                                            }
191                                            else
192                                            {
193                                                    REPEAT(line[x] = prevline[x] ^ mix);
194                                            }
195                                            break;
196    
197                                    case 2: /* Fill or Mix */
198                                            if (prevline == NULL)
199                                            {
200                                                    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                                    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;                                          break;
240    
241                                  default:                                  default:
242                                          fprintf(stderr, "Undefined escape 0x%X\n", code);                                          unimpl("bitmap opcode 0x%x\n", opcode);
243                                          return False;                                          return False;
                                 }  
244                          }                          }
245                  }                  }
246          }          }
247    
248          printf("Uncompressed size: %d\n", output - start);          return True;
249  #if BITMAP_DEBUG  }
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                  static int bmpno = 1;                  fom_mask = 0;
267                  char filename[64];                  code = CVAL(input);
268                    opcode = code >> 4;
269    
270                  snprintf(filename, sizeof(filename)-1, "in%d.raw", bmpno);                  /* Handle different opcode forms */
271                  hexdump(filename, savedinput, size);                  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                  snprintf(filename, sizeof(filename)-1, "out%d.raw", bmpno);                          case 0xf:
282                  hexdump(filename, start, output-start);                                  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                  bmpno++;                          default:
296          }                                  opcode >>= 1;
297  #endif                                  count = code & 0x1f;
298                                    offset = 32;
299                                    break;
300                    }
301    
302          return True;                  /* 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  #if BITMAP_DEBUG                  }
 void hexdump(char *filename, unsigned char *data, int length)  
 {  
         /*  
         int i;  
349    
350          for (i = 0; i < length; i++)                  lastopcode = opcode;
351          {                  mixmask = 0;
352                  printf("%02X ", data[i]);  
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;
375                                                    else
376                                                            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
388                                            {
389                                                    REPEAT(line[x] = prevline[x]);
390                                            }
391                                            break;
392    
393                                    case 1: /* Mix */
394                                            if (prevline == NULL)
395                                            {
396                                                    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;
421    
422                                    case 3: /* Colour */
423                                            REPEAT(line[x] = colour2);
424                                            break;
425    
426                  if (i % 16 == 15)                                  case 4: /* Copy */
427                          printf("\n");                                          REPEAT(line[x] = CVAL16(input));
428                                            break;
429    
430                                    case 8: /* Bicolour */
431                                            REPEAT(if (bicolour)
432                                                   {
433                                                   line[x] = colour2; bicolour = False;}
434                                                   else
435                                                   {
436                                                   line[x] = colour1; bicolour = True; count++;}
437                                            );
438                                            break;
439    
440                                    case 0xd:       /* White */
441                                            REPEAT(line[x] = 0xffff);
442                                            break;
443    
444                                    case 0xe:       /* Black */
445                                            REPEAT(line[x] = 0x00);
446                                            break;
447    
448                                    default:
449                                            unimpl("bitmap opcode 0x%x\n", opcode);
450                                            return False;
451                            }
452                    }
453          }          }
         */  
454    
455          int fd;          return True;
456    }
457    
458          fd = open(filename, O_WRONLY|O_CREAT, 0600);  BOOL
459          write(fd, data, length);  bitmap_decompress(unsigned char *output, int width, int height, unsigned char *input, int size, int bpp)
460          close(fd);  {
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  }  }
 #endif  

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

  ViewVC Help
Powered by ViewVC 1.1.26