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

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

  ViewVC Help
Powered by ViewVC 1.1.26