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

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

  ViewVC Help
Powered by ViewVC 1.1.26