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

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 693 by stargo, Fri May 7 04:57:39 2004 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"  /* three seperate function for speed when decompressing the bitmaps */
22  #include <fcntl.h>  /* when modifing one function make the change in the others */
23    /* comment out #define BITMAP_SPEED_OVER_SIZE below for one slower function */
24  #define BITMAP_DEBUG 1  /* j@american-data.com */
25    
26    #define BITMAP_SPEED_OVER_SIZE
27    
28    /* indent is confused by this file */
29    /* *INDENT-OFF* */
30    
31    #include "rdesktop.h"
32    
33    #define CVAL(p)   (*(p++))
34    #ifdef NEED_ALIGN
35    #ifdef L_ENDIAN
36    #define CVAL2(p, v) { v = (*(p++)); v |= (*(p++)) << 8; }
37    #else
38    #define CVAL2(p, v) { v = (*(p++)) << 8; v |= (*(p++)); }
39    #endif /* L_ENDIAN */
40    #else
41    #define CVAL2(p, v) v = (*(((uint16*)p)++));
42    #endif /* NEED_ALIGN */
43    
44    #define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
45    
46    #define REPEAT(statement) \
47    { \
48            while((count & ~0x7) && ((x+8) < width)) \
49                    UNROLL8( statement; count--; x++; ); \
50            \
51            while((count > 0) && (x < width)) \
52            { \
53                    statement; \
54                    count--; \
55                    x++; \
56            } \
57    }
58    
59  #if BITMAP_DEBUG  #define MASK_UPDATE() \
60  void hexdump(char *filename, unsigned char *data, int length);  { \
61  #endif          mixmask <<= 1; \
62            if (mixmask == 0) \
63            { \
64                    mask = fom_mask ? fom_mask : CVAL(input); \
65                    mixmask = 1; \
66            } \
67    }
68    
69  #define RCVAL()   (*(input++))  #ifdef BITMAP_SPEED_OVER_SIZE
 #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); }}  
70    
71  BOOL bitmap_decompress(unsigned char *input, int size,  /* 1 byte bitmap decompress */
72                         unsigned char *output, int width)  static BOOL
73    bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size)
74  {  {
75          unsigned char *savedinput = input;          uint8 *end = input + size;
76          unsigned char *start = output;          uint8 *prevline = NULL, *line = NULL;
77          unsigned char *end = input + size;          int opcode, count, offset, isfillormix, x = width;
78          unsigned char code;          int lastopcode = -1, insertmix = False, bicolour = False;
79          unsigned char mix = 0xFF;          uint8 code;
80          int n, savedn;          uint8 colour1 = 0, colour2 = 0;
81            uint8 mixmask, mask = 0;
82            uint8 mix = 0xff;
83            int fom_mask = 0;
84    
85          while (input < end)          while (input < end)
86          {          {
87                  code = RCVAL();                  fom_mask = 0;
88                  switch (code)                  code = CVAL(input);
89                    opcode = code >> 4;
90                    /* Handle different opcode forms */
91                    switch (opcode)
92                  {                  {
93                  case 0x00: // Fill                          case 0xc:
94                          n = RCVAL() + 32;                          case 0xd:
95                          FILL();                          case 0xe:
96                          break;                                  opcode -= 6;
97                  case 0xF0: // Fill                                  count = code & 0xf;
98                          n = RSVAL();                                  offset = 16;
99                          FILL();                                  break;
100                          break;                          case 0xf:
101                  case 0x20: // Mix                                  opcode = code & 0xf;
102                          n = RCVAL() + 32;                                  if (opcode < 9)
103                          MIX();                                  {
104                          break;                                          count = CVAL(input);
105                  case 0xF1: // Mix                                          count |= CVAL(input) << 8;
106                          n = RSVAL();                                  }
107                          MIX();                                  else
108                          break;                                  {
109                  case 0x40: // FillOrMix                                          count = (opcode < 0xb) ? 8 : 1;
110                          fprintf(stderr, "FillOrMix unsupported\n");                                  }
111                          savedn = n = RCVAL() + 1;                                  offset = 0;
112                          MIX();                                  break;
113                          input += (savedn+7)/8;                          default:
114                          break;                                  opcode >>= 1;
115                  case 0xF2:                                  count = code & 0x1f;
116                          fprintf(stderr, "FillOrMix unsupported\n");                                  offset = 32;
117                          savedn = n = RSVAL();                                  break;
118                          MIX();                  }
119                          input += (savedn+7)/8;                  /* Handle strange cases for counts */
120                          break;                  if (offset != 0)
121                  case 0x60: // Color                  {
122                          n = RCVAL() + 32;                          isfillormix = ((opcode == 2) || (opcode == 7));
123                          COLOR();                          if (count == 0)
                         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;  
   
                         if (n == 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                  /* Read preliminary data */
136                                  MIX();                  switch (opcode)
137                    {
138                            case 0: /* Fill */
139                                    if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
140                                            insertmix = True;
141                                  break;                                  break;
142                          case 2: // FillOrMix                          case 8: /* Bicolour */
143                                  fprintf(stderr, "FillOrMix unsupported\n");                                  colour1 = CVAL(input);
144                                  n *= 8;                          case 3: /* Colour */
145                                  savedn = n;                                  colour2 = CVAL(input);
                                 MIX();  
                                 input += (savedn+7)/8;  
146                                  break;                                  break;
147                          case 3: // Color                          case 6: /* SetMix/Mix */
148                                  COLOR();                          case 7: /* SetMix/FillOrMix */
149                                    mix = CVAL(input);
150                                    opcode -= 5;
151                                  break;                                  break;
152                          case 4: // Copy                          case 9: /* FillOrMix_1 */
153                                  COPY();                                  mask = 0x03;
154                                    opcode = 0x02;
155                                    fom_mask = 3;
156                                  break;                                  break;
157                          case 5: // Copy Packed                          case 0x0a:      /* FillOrMix_2 */
158                                  fprintf(stderr, "CopyPacked 3\n");                                  mask = 0x05;
159                                  COPY_PACKED();                                  opcode = 0x02;
160                                    fom_mask = 5;
161                                  break;                                  break;
162                          case 6:                  }
163                                  n = code & 15;                  lastopcode = opcode;
164                    mixmask = 0;
165                    /* Output body */
166                    while (count > 0)
167                    {
168                            if (x >= width)
169                            {
170                                    if (height <= 0)
171                                            return False;
172                                    x = 0;
173                                    height--;
174                                    prevline = line;
175                                    line = output + height * width;
176                            }
177                            switch (opcode)
178                            {
179                                    case 0: /* Fill */
180                                            if (insertmix)
181                                            {
182                                                    if (prevline == NULL)
183                                                            line[x] = mix;
184                                                    else
185                                                            line[x] = prevline[x] ^ mix;
186                                                    insertmix = False;
187                                                    count--;
188                                                    x++;
189                                            }
190                                            if (prevline == NULL)
191                                            {
192                                                    REPEAT(line[x] = 0)
193                                            }
194                                            else
195                                            {
196                                                    REPEAT(line[x] = prevline[x])
197                                            }
198                                            break;
199                                    case 1: /* Mix */
200                                            if (prevline == NULL)
201                                            {
202                                                    REPEAT(line[x] = mix)
203                                            }
204                                            else
205                                            {
206                                                    REPEAT(line[x] = prevline[x] ^ mix)
207                                            }
208                                            break;
209                                    case 2: /* Fill or Mix */
210                                            if (prevline == NULL)
211                                            {
212                                                    REPEAT
213                                                    (
214                                                            MASK_UPDATE();
215                                                            if (mask & mixmask)
216                                                                    line[x] = mix;
217                                                            else
218                                                                    line[x] = 0;
219                                                    )
220                                            }
221                                            else
222                                            {
223                                                    REPEAT
224                                                    (
225                                                            MASK_UPDATE();
226                                                            if (mask & mixmask)
227                                                                    line[x] = prevline[x] ^ mix;
228                                                            else
229                                                                    line[x] = prevline[x];
230                                                    )
231                                            }
232                                            break;
233                                    case 3: /* Colour */
234                                            REPEAT(line[x] = colour2)
235                                            break;
236                                    case 4: /* Copy */
237                                            REPEAT(line[x] = CVAL(input))
238                                            break;
239                                    case 8: /* Bicolour */
240                                            REPEAT
241                                            (
242                                                    if (bicolour)
243                                                    {
244                                                            line[x] = colour2;
245                                                            bicolour = False;
246                                                    }
247                                                    else
248                                                    {
249                                                            line[x] = colour1;
250                                                            bicolour = True; count++;
251                                                    }
252                                            )
253                                            break;
254                                    case 0xd:       /* White */
255                                            REPEAT(line[x] = 0xff)
256                                            break;
257                                    case 0xe:       /* Black */
258                                            REPEAT(line[x] = 0)
259                                            break;
260                                    default:
261                                            unimpl("bitmap opcode 0x%x\n", opcode);
262                                            return False;
263                            }
264                    }
265            }
266            return True;
267    }
268    
269    /* 2 byte bitmap decompress */
270    static BOOL
271    bitmap_decompress2(uint8 * output, int width, int height, uint8 * input, int size)
272    {
273            uint8 *end = input + size;
274            uint16 *prevline = NULL, *line = NULL;
275            int opcode, count, offset, isfillormix, x = width;
276            int lastopcode = -1, insertmix = False, bicolour = False;
277            uint8 code;
278            uint16 colour1 = 0, colour2 = 0;
279            uint8 mixmask, mask = 0;
280            uint16 mix = 0xffff;
281            int fom_mask = 0;
282    
283                                  switch ((code >> 4) & 15)          while (input < end)
284            {
285                    fom_mask = 0;
286                    code = CVAL(input);
287                    opcode = code >> 4;
288                    /* Handle different opcode forms */
289                    switch (opcode)
290                    {
291                            case 0xc:
292                            case 0xd:
293                            case 0xe:
294                                    opcode -= 6;
295                                    count = code & 0xf;
296                                    offset = 16;
297                                    break;
298                            case 0xf:
299                                    opcode = code & 0xf;
300                                    if (opcode < 9)
301                                  {                                  {
302                                  case 0xC:                                          count = CVAL(input);
303                                          fprintf(stderr, "SetMix_Mix 3\n");                                          count |= CVAL(input) << 8;
304                                          SETMIX_MIX();                                  }
305                                          break;                                  else
306                                  case 0xD:                                  {
307                                          fprintf(stderr, "SetMix_FillOrMix unsupported\n");                                          count = (opcode < 0xb) ? 8 : 1;
308                                          n *= 8;                                  }
309                                          savedn = n;                                  offset = 0;
310                                          SETMIX_MIX();                                  break;
311                                          input += (savedn+7)/8;                          default:
312                                          break;                                  opcode >>= 1;
313                                  case 0xE:                                  count = code & 0x1f;
314                                          fprintf(stderr, "Bicolor 3\n");                                  offset = 32;
315                                          BICOLOR();                                  break;
316                    }
317                    /* Handle strange cases for counts */
318                    if (offset != 0)
319                    {
320                            isfillormix = ((opcode == 2) || (opcode == 7));
321                            if (count == 0)
322                            {
323                                    if (isfillormix)
324                                            count = CVAL(input) + 1;
325                                    else
326                                            count = CVAL(input) + offset;
327                            }
328                            else if (isfillormix)
329                            {
330                                    count <<= 3;
331                            }
332                    }
333                    /* Read preliminary data */
334                    switch (opcode)
335                    {
336                            case 0: /* Fill */
337                                    if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
338                                            insertmix = True;
339                                    break;
340                            case 8: /* Bicolour */
341                                    CVAL2(input, colour1);
342                            case 3: /* Colour */
343                                    CVAL2(input, colour2);
344                                    break;
345                            case 6: /* SetMix/Mix */
346                            case 7: /* SetMix/FillOrMix */
347                                    CVAL2(input, mix);
348                                    opcode -= 5;
349                                    break;
350                            case 9: /* FillOrMix_1 */
351                                    mask = 0x03;
352                                    opcode = 0x02;
353                                    fom_mask = 3;
354                                    break;
355                            case 0x0a:      /* FillOrMix_2 */
356                                    mask = 0x05;
357                                    opcode = 0x02;
358                                    fom_mask = 5;
359                                    break;
360                    }
361                    lastopcode = opcode;
362                    mixmask = 0;
363                    /* Output body */
364                    while (count > 0)
365                    {
366                            if (x >= width)
367                            {
368                                    if (height <= 0)
369                                            return False;
370                                    x = 0;
371                                    height--;
372                                    prevline = line;
373                                    line = ((uint16 *) output) + height * width;
374                            }
375                            switch (opcode)
376                            {
377                                    case 0: /* Fill */
378                                            if (insertmix)
379                                            {
380                                                    if (prevline == NULL)
381                                                            line[x] = mix;
382                                                    else
383                                                            line[x] = prevline[x] ^ mix;
384                                                    insertmix = False;
385                                                    count--;
386                                                    x++;
387                                            }
388                                            if (prevline == NULL)
389                                            {
390                                                    REPEAT(line[x] = 0)
391                                            }
392                                            else
393                                            {
394                                                    REPEAT(line[x] = prevline[x])
395                                            }
396                                            break;
397                                    case 1: /* Mix */
398                                            if (prevline == NULL)
399                                            {
400                                                    REPEAT(line[x] = mix)
401                                            }
402                                            else
403                                            {
404                                                    REPEAT(line[x] = prevline[x] ^ mix)
405                                            }
406                                            break;
407                                    case 2: /* Fill or Mix */
408                                            if (prevline == NULL)
409                                            {
410                                                    REPEAT
411                                                    (
412                                                            MASK_UPDATE();
413                                                            if (mask & mixmask)
414                                                                    line[x] = mix;
415                                                            else
416                                                                    line[x] = 0;
417                                                    )
418                                            }
419                                            else
420                                            {
421                                                    REPEAT
422                                                    (
423                                                            MASK_UPDATE();
424                                                            if (mask & mixmask)
425                                                                    line[x] = prevline[x] ^ mix;
426                                                            else
427                                                                    line[x] = prevline[x];
428                                                    )
429                                            }
430                                            break;
431                                    case 3: /* Colour */
432                                            REPEAT(line[x] = colour2)
433                                            break;
434                                    case 4: /* Copy */
435                                            REPEAT(CVAL2(input, line[x]))
436                                            break;
437                                    case 8: /* Bicolour */
438                                            REPEAT
439                                            (
440                                                    if (bicolour)
441                                                    {
442                                                            line[x] = colour2;
443                                                            bicolour = False;
444                                                    }
445                                                    else
446                                                    {
447                                                            line[x] = colour1;
448                                                            bicolour = True;
449                                                            count++;
450                                                    }
451                                            )
452                                            break;
453                                    case 0xd:       /* White */
454                                            REPEAT(line[x] = 0xffff)
455                                            break;
456                                    case 0xe:       /* Black */
457                                            REPEAT(line[x] = 0)
458                                          break;                                          break;
459                                  default:                                  default:
460                                          fprintf(stderr, "Undefined escape 0x%X\n", code);                                          unimpl("bitmap opcode 0x%x\n", opcode);
461                                          return False;                                          return False;
                                 }  
462                          }                          }
463                  }                  }
464          }          }
465            return True;
466    }
467    
468          printf("Uncompressed size: %d\n", output - start);  /* 3 byte bitmap decompress */
469  #if BITMAP_DEBUG  static BOOL
470          {  bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int size)
471                  static int bmpno = 1;  {
472                  char filename[64];          uint8 *end = input + size;
473            uint8 *prevline = NULL, *line = NULL;
474            int opcode, count, offset, isfillormix, x = width;
475            int lastopcode = -1, insertmix = False, bicolour = False;
476            uint8 code;
477            uint8 colour1[3] = {0, 0, 0}, colour2[3] = {0, 0, 0};
478            uint8 mixmask, mask = 0;
479            uint8 mix[3] = {0xff, 0xff, 0xff};
480            int fom_mask = 0;
481    
482                  snprintf(filename, sizeof(filename)-1, "in%d.raw", bmpno);          while (input < end)
483                  hexdump(filename, savedinput, size);          {
484                    fom_mask = 0;
485                    code = CVAL(input);
486                    opcode = code >> 4;
487                    /* Handle different opcode forms */
488                    switch (opcode)
489                    {
490                            case 0xc:
491                            case 0xd:
492                            case 0xe:
493                                    opcode -= 6;
494                                    count = code & 0xf;
495                                    offset = 16;
496                                    break;
497                            case 0xf:
498                                    opcode = code & 0xf;
499                                    if (opcode < 9)
500                                    {
501                                            count = CVAL(input);
502                                            count |= CVAL(input) << 8;
503                                    }
504                                    else
505                                    {
506                                            count = (opcode <
507                                                     0xb) ? 8 : 1;
508                                    }
509                                    offset = 0;
510                                    break;
511                            default:
512                                    opcode >>= 1;
513                                    count = code & 0x1f;
514                                    offset = 32;
515                                    break;
516                    }
517                    /* Handle strange cases for counts */
518                    if (offset != 0)
519                    {
520                            isfillormix = ((opcode == 2) || (opcode == 7));
521                            if (count == 0)
522                            {
523                                    if (isfillormix)
524                                            count = CVAL(input) + 1;
525                                    else
526                                            count = CVAL(input) + offset;
527                            }
528                            else if (isfillormix)
529                            {
530                                    count <<= 3;
531                            }
532                    }
533                    /* Read preliminary data */
534                    switch (opcode)
535                    {
536                            case 0: /* Fill */
537                                    if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
538                                            insertmix = True;
539                                    break;
540                            case 8: /* Bicolour */
541                                    colour1[0] = CVAL(input);
542                                    colour1[1] = CVAL(input);
543                                    colour1[2] = CVAL(input);
544                            case 3: /* Colour */
545                                    colour2[0] = CVAL(input);
546                                    colour2[1] = CVAL(input);
547                                    colour2[2] = CVAL(input);
548                                    break;
549                            case 6: /* SetMix/Mix */
550                            case 7: /* SetMix/FillOrMix */
551                                    mix[0] = CVAL(input);
552                                    mix[1] = CVAL(input);
553                                    mix[2] = CVAL(input);
554                                    opcode -= 5;
555                                    break;
556                            case 9: /* FillOrMix_1 */
557                                    mask = 0x03;
558                                    opcode = 0x02;
559                                    fom_mask = 3;
560                                    break;
561                            case 0x0a:      /* FillOrMix_2 */
562                                    mask = 0x05;
563                                    opcode = 0x02;
564                                    fom_mask = 5;
565                                    break;
566                    }
567                    lastopcode = opcode;
568                    mixmask = 0;
569                    /* Output body */
570                    while (count > 0)
571                    {
572                            if (x >= width)
573                            {
574                                    if (height <= 0)
575                                            return False;
576                                    x = 0;
577                                    height--;
578                                    prevline = line;
579                                    line = output + height * (width * 3);
580                            }
581                            switch (opcode)
582                            {
583                                    case 0: /* Fill */
584                                            if (insertmix)
585                                            {
586                                                    if (prevline == NULL)
587                                                    {
588                                                            line[x * 3] = mix[0];
589                                                            line[x * 3 + 1] = mix[1];
590                                                            line[x * 3 + 2] = mix[2];
591                                                    }
592                                                    else
593                                                    {
594                                                            line[x * 3] =
595                                                             prevline[x * 3] ^ mix[0];
596                                                            line[x * 3 + 1] =
597                                                             prevline[x * 3 + 1] ^ mix[1];
598                                                            line[x * 3 + 2] =
599                                                             prevline[x * 3 + 2] ^ mix[2];
600                                                    }
601                                                    insertmix = False;
602                                                    count--;
603                                                    x++;
604                                            }
605                                            if (prevline == NULL)
606                                            {
607                                                    REPEAT
608                                                    (
609                                                            line[x * 3] = 0;
610                                                            line[x * 3 + 1] = 0;
611                                                            line[x * 3 + 2] = 0;
612                                                    )
613                                            }
614                                            else
615                                            {
616                                                    REPEAT
617                                                    (
618                                                            line[x * 3] = prevline[x * 3];
619                                                            line[x * 3 + 1] = prevline[x * 3 + 1];
620                                                            line[x * 3 + 2] = prevline[x * 3 + 2];
621                                                    )
622                                            }
623                                            break;
624                                    case 1: /* Mix */
625                                            if (prevline == NULL)
626                                            {
627                                                    REPEAT
628                                                    (
629                                                            line[x * 3] = mix[0];
630                                                            line[x * 3 + 1] = mix[1];
631                                                            line[x * 3 + 2] = mix[2];
632                                                    )
633                                            }
634                                            else
635                                            {
636                                                    REPEAT
637                                                    (
638                                                            line[x * 3] =
639                                                             prevline[x * 3] ^ mix[0];
640                                                            line[x * 3 + 1] =
641                                                             prevline[x * 3 + 1] ^ mix[1];
642                                                            line[x * 3 + 2] =
643                                                             prevline[x * 3 + 2] ^ mix[2];
644                                                    )
645                                            }
646                                            break;
647                                    case 2: /* Fill or Mix */
648                                            if (prevline == NULL)
649                                            {
650                                                    REPEAT
651                                                    (
652                                                            MASK_UPDATE();
653                                                            if (mask & mixmask)
654                                                            {
655                                                                    line[x * 3] = mix[0];
656                                                                    line[x * 3 + 1] = mix[1];
657                                                                    line[x * 3 + 2] = mix[2];
658                                                            }
659                                                            else
660                                                            {
661                                                                    line[x * 3] = 0;
662                                                                    line[x * 3 + 1] = 0;
663                                                                    line[x * 3 + 2] = 0;
664                                                            }
665                                                    )
666                                            }
667                                            else
668                                            {
669                                                    REPEAT
670                                                    (
671                                                            MASK_UPDATE();
672                                                            if (mask & mixmask)
673                                                            {
674                                                                    line[x * 3] =
675                                                                     prevline[x * 3] ^ mix [0];
676                                                                    line[x * 3 + 1] =
677                                                                     prevline[x * 3 + 1] ^ mix [1];
678                                                                    line[x * 3 + 2] =
679                                                                     prevline[x * 3 + 2] ^ mix [2];
680                                                            }
681                                                            else
682                                                            {
683                                                                    line[x * 3] =
684                                                                     prevline[x * 3];
685                                                                    line[x * 3 + 1] =
686                                                                     prevline[x * 3 + 1];
687                                                                    line[x * 3 + 2] =
688                                                                     prevline[x * 3 + 2];
689                                                            }
690                                                    )
691                                            }
692                                            break;
693                                    case 3: /* Colour */
694                                            REPEAT
695                                            (
696                                                    line[x * 3] = colour2 [0];
697                                                    line[x * 3 + 1] = colour2 [1];
698                                                    line[x * 3 + 2] = colour2 [2];
699                                            )
700                                            break;
701                                    case 4: /* Copy */
702                                            REPEAT
703                                            (
704                                                    line[x * 3] = CVAL(input);
705                                                    line[x * 3 + 1] = CVAL(input);
706                                                    line[x * 3 + 2] = CVAL(input);
707                                            )
708                                            break;
709                                    case 8: /* Bicolour */
710                                            REPEAT
711                                            (
712                                                    if (bicolour)
713                                                    {
714                                                            line[x * 3] = colour2[0];
715                                                            line[x * 3 + 1] = colour2[1];
716                                                            line[x * 3 + 2] = colour2[2];
717                                                            bicolour = False;
718                                                    }
719                                                    else
720                                                    {
721                                                            line[x * 3] = colour1[0];
722                                                            line[x * 3 + 1] = colour1[1];
723                                                            line[x * 3 + 2] = colour1[2];
724                                                            bicolour = True;
725                                                            count++;
726                                                    }
727                                            )
728                                            break;
729                                    case 0xd:       /* White */
730                                            REPEAT
731                                            (
732                                                    line[x * 3] = 0xff;
733                                                    line[x * 3 + 1] = 0xff;
734                                                    line[x * 3 + 2] = 0xff;
735                                            )
736                                            break;
737                                    case 0xe:       /* Black */
738                                            REPEAT
739                                            (
740                                                    line[x * 3] = 0;
741                                                    line[x * 3 + 1] = 0;
742                                                    line[x * 3 + 2] = 0;
743                                            )
744                                            break;
745                                    default:
746                                            unimpl("bitmap opcode 0x%x\n", opcode);
747                                            return False;
748                            }
749                    }
750            }
751            return True;
752    }
753    
754                  snprintf(filename, sizeof(filename)-1, "out%d.raw", bmpno);  #else
                 hexdump(filename, start, output-start);  
755    
756                  bmpno++;  static uint32
757          }  cvalx(uint8 **input, int Bpp)
758  #endif  {
759            uint32 rv = 0;
760            memcpy(&rv, *input, Bpp);
761            *input += Bpp;
762            return rv;
763    }
764    
765          return True;  static void
766    setli(uint8 *input, int offset, uint32 value, int Bpp)
767    {
768            input += offset * Bpp;
769            memcpy(input, &value, Bpp);
770  }  }
771    
772    static uint32
773    getli(uint8 *input, int offset, int Bpp)
774    {
775            uint32 rv = 0;
776            input += offset * Bpp;
777            memcpy(&rv, input, Bpp);
778            return rv;
779    }
780    
781  #if BITMAP_DEBUG  static BOOL
782  void hexdump(char *filename, unsigned char *data, int length)  bitmap_decompressx(uint8 *output, int width, int height, uint8 *input, int size, int Bpp)
783  {  {
784          /*          uint8 *end = input + size;
785          int i;          uint8 *prevline = NULL, *line = NULL;
786            int opcode, count, offset, isfillormix, x = width;
787            int lastopcode = -1, insertmix = False, bicolour = False;
788            uint8 code;
789            uint32 colour1 = 0, colour2 = 0;
790            uint8 mixmask, mask = 0;
791            uint32 mix = 0xffffffff;
792            int fom_mask = 0;
793    
794          for (i = 0; i < length; i++)          while (input < end)
795          {          {
796                  printf("%02X ", data[i]);                  fom_mask = 0;
797                    code = CVAL(input);
798                    opcode = code >> 4;
799    
800                  if (i % 16 == 15)                  /* Handle different opcode forms */
801                          printf("\n");                  switch (opcode)
802          }                  {
803          */                          case 0xc:
804                            case 0xd:
805                            case 0xe:
806                                    opcode -= 6;
807                                    count = code & 0xf;
808                                    offset = 16;
809                                    break;
810    
811                            case 0xf:
812                                    opcode = code & 0xf;
813                                    if (opcode < 9)
814                                    {
815                                            count = CVAL(input);
816                                            count |= CVAL(input) << 8;
817                                    }
818                                    else
819                                    {
820                                            count = (opcode < 0xb) ? 8 : 1;
821                                    }
822                                    offset = 0;
823                                    break;
824    
825                            default:
826                                    opcode >>= 1;
827                                    count = code & 0x1f;
828                                    offset = 32;
829                                    break;
830                    }
831    
832                    /* Handle strange cases for counts */
833                    if (offset != 0)
834                    {
835                            isfillormix = ((opcode == 2) || (opcode == 7));
836    
837          int fd;                          if (count == 0)
838                            {
839                                    if (isfillormix)
840                                            count = CVAL(input) + 1;
841                                    else
842                                            count = CVAL(input) + offset;
843                            }
844                            else if (isfillormix)
845                            {
846                                    count <<= 3;
847                            }
848                    }
849    
850                    /* Read preliminary data */
851                    switch (opcode)
852                    {
853                            case 0: /* Fill */
854                                    if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
855                                            insertmix = True;
856                                    break;
857                            case 8: /* Bicolour */
858                                    colour1 = cvalx(&input, Bpp);
859                            case 3: /* Colour */
860                                    colour2 = cvalx(&input, Bpp);
861                                    break;
862                            case 6: /* SetMix/Mix */
863                            case 7: /* SetMix/FillOrMix */
864                                    mix = cvalx(&input, Bpp);
865                                    opcode -= 5;
866                                    break;
867                            case 9: /* FillOrMix_1 */
868                                    mask = 0x03;
869                                    opcode = 0x02;
870                                    fom_mask = 3;
871                                    break;
872                            case 0x0a:      /* FillOrMix_2 */
873                                    mask = 0x05;
874                                    opcode = 0x02;
875                                    fom_mask = 5;
876                                    break;
877    
878                    }
879    
880                    lastopcode = opcode;
881                    mixmask = 0;
882    
883                    /* Output body */
884                    while (count > 0)
885                    {
886                            if (x >= width)
887                            {
888                                    if (height <= 0)
889                                            return False;
890    
891                                    x = 0;
892                                    height--;
893    
894                                    prevline = line;
895                                    line = output + height * width * Bpp;
896                            }
897    
898                            switch (opcode)
899                            {
900                                    case 0: /* Fill */
901                                            if (insertmix)
902                                            {
903                                                    if (prevline == NULL)
904                                                            setli(line, x, mix, Bpp);
905                                                    else
906                                                            setli(line, x,
907                                                                  getli(prevline, x, Bpp) ^ mix, Bpp);
908    
909                                                    insertmix = False;
910                                                    count--;
911                                                    x++;
912                                            }
913    
914                                            if (prevline == NULL)
915                                            {
916                                            REPEAT(setli(line, x, 0, Bpp))}
917                                            else
918                                            {
919                                                    REPEAT(setli
920                                                           (line, x, getli(prevline, x, Bpp), Bpp));
921                                            }
922                                            break;
923    
924                                    case 1: /* Mix */
925                                            if (prevline == NULL)
926                                            {
927                                                    REPEAT(setli(line, x, mix, Bpp));
928                                            }
929                                            else
930                                            {
931                                                    REPEAT(setli
932                                                           (line, x, getli(prevline, x, Bpp) ^ mix,
933                                                            Bpp));
934                                            }
935                                            break;
936    
937                                    case 2: /* Fill or Mix */
938                                            if (prevline == NULL)
939                                            {
940                                                    REPEAT(MASK_UPDATE();
941                                                           if (mask & mixmask) setli(line, x, mix, Bpp);
942                                                           else
943                                                           setli(line, x, 0, Bpp););
944                                            }
945                                            else
946                                            {
947                                                    REPEAT(MASK_UPDATE();
948                                                           if (mask & mixmask)
949                                                           setli(line, x, getli(prevline, x, Bpp) ^ mix,
950                                                                 Bpp);
951                                                           else
952                                                           setli(line, x, getli(prevline, x, Bpp),
953                                                                 Bpp););
954                                            }
955                                            break;
956    
957          fd = open(filename, O_WRONLY|O_CREAT, 0600);                                  case 3: /* Colour */
958          write(fd, data, length);                                          REPEAT(setli(line, x, colour2, Bpp));
959          close(fd);                                          break;
960    
961                                    case 4: /* Copy */
962                                            REPEAT(setli(line, x, cvalx(&input, Bpp), Bpp));
963                                            break;
964    
965                                    case 8: /* Bicolour */
966                                            REPEAT(if (bicolour)
967                                                   {
968                                                   setli(line, x, colour2, Bpp); bicolour = False;}
969                                                   else
970                                                   {
971                                                   setli(line, x, colour1, Bpp); bicolour = True;
972                                                   count++;}
973                                            );
974                                            break;
975    
976                                    case 0xd:       /* White */
977                                            REPEAT(setli(line, x, 0xffffffff, Bpp));
978                                            break;
979    
980                                    case 0xe:       /* Black */
981                                            REPEAT(setli(line, x, 0, Bpp));
982                                            break;
983    
984                                    default:
985                                            unimpl("bitmap opcode 0x%x\n", opcode);
986                                            return False;
987                            }
988                    }
989            }
990    
991            return True;
992  }  }
993    
994    #endif
995    
996    /* main decompress function */
997    BOOL
998    bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp)
999    {
1000    #ifdef BITMAP_SPEED_OVER_SIZE
1001            BOOL rv = False;
1002            switch (Bpp)
1003            {
1004                    case 1:
1005                            rv = bitmap_decompress1(output, width, height, input, size);
1006                            break;
1007                    case 2:
1008                            rv = bitmap_decompress2(output, width, height, input, size);
1009                            break;
1010                    case 3:
1011                            rv = bitmap_decompress3(output, width, height, input, size);
1012                            break;
1013            }
1014    #else
1015            BOOL rv;
1016      rv = bitmap_decompressx(output, width, height, input, size, Bpp);
1017  #endif  #endif
1018            return rv;
1019    }
1020    
1021    /* *INDENT-ON* */

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

  ViewVC Help
Powered by ViewVC 1.1.26