/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/bitmap.c

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

revision 207 by matthewc, Thu Sep 26 14:26:46 2002 UTC revision 1417 by jsorg71, Thu Aug 30 04:47:36 2007 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-2002     Copyright (C) Matthew Chapman 1999-2007
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    /* three seperate function for speed when decompressing the bitmaps
22       when modifing one function make the change in the others
23       jay.sorg@gmail.com */
24    
25    /* indent is confused by this file */
26    /* *INDENT-OFF* */
27    
28  #include "rdesktop.h"  #include "rdesktop.h"
29    
30  #define CVAL(p)   (*(p++))  #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 }  #define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
42    
# Line 29  Line 45 
45          while((count & ~0x7) && ((x+8) < width)) \          while((count & ~0x7) && ((x+8) < width)) \
46                  UNROLL8( statement; count--; x++; ); \                  UNROLL8( statement; count--; x++; ); \
47          \          \
48          while((count > 0) && (x < width)) { statement; count--; x++; } \          while((count > 0) && (x < width)) \
49            { \
50                    statement; \
51                    count--; \
52                    x++; \
53            } \
54  }  }
55    
56  #define MASK_UPDATE() \  #define MASK_UPDATE() \
# Line 42  Line 63 
63          } \          } \
64  }  }
65    
66  BOOL  /* 1 byte bitmap decompress */
67  bitmap_decompress(unsigned char *output, int width, int height, unsigned char *input, int size)  static RD_BOOL
68    bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size)
69  {  {
70          unsigned char *end = input + size;          uint8 *end = input + size;
71          unsigned char *prevline = NULL, *line = NULL;          uint8 *prevline = NULL, *line = NULL;
72          int opcode, count, offset, isfillormix, x = width;          int opcode, count, offset, isfillormix, x = width;
73          int lastopcode = -1, insertmix = False, bicolour = False;          int lastopcode = -1, insertmix = False, bicolour = False;
74          uint8 code, colour1 = 0, colour2 = 0;          uint8 code;
75          uint8 mixmask, mask = 0, mix = 0xff;          uint8 colour1 = 0, colour2 = 0;
76            uint8 mixmask, mask = 0;
77            uint8 mix = 0xff;
78          int fom_mask = 0;          int fom_mask = 0;
79    
80          while (input < end)          while (input < end)
# Line 58  bitmap_decompress(unsigned char *output, Line 82  bitmap_decompress(unsigned char *output,
82                  fom_mask = 0;                  fom_mask = 0;
83                  code = CVAL(input);                  code = CVAL(input);
84                  opcode = code >> 4;                  opcode = code >> 4;
   
85                  /* Handle different opcode forms */                  /* Handle different opcode forms */
86                  switch (opcode)                  switch (opcode)
87                  {                  {
# Line 69  bitmap_decompress(unsigned char *output, Line 92  bitmap_decompress(unsigned char *output,
92                                  count = code & 0xf;                                  count = code & 0xf;
93                                  offset = 16;                                  offset = 16;
94                                  break;                                  break;
   
95                          case 0xf:                          case 0xf:
96                                  opcode = code & 0xf;                                  opcode = code & 0xf;
97                                  if (opcode < 9)                                  if (opcode < 9)
# Line 83  bitmap_decompress(unsigned char *output, Line 105  bitmap_decompress(unsigned char *output,
105                                  }                                  }
106                                  offset = 0;                                  offset = 0;
107                                  break;                                  break;
   
108                          default:                          default:
109                                  opcode >>= 1;                                  opcode >>= 1;
110                                  count = code & 0x1f;                                  count = code & 0x1f;
111                                  offset = 32;                                  offset = 32;
112                                  break;                                  break;
113                  }                  }
   
114                  /* Handle strange cases for counts */                  /* Handle strange cases for counts */
115                  if (offset != 0)                  if (offset != 0)
116                  {                  {
117                          isfillormix = ((opcode == 2) || (opcode == 7));                          isfillormix = ((opcode == 2) || (opcode == 7));
   
118                          if (count == 0)                          if (count == 0)
119                          {                          {
120                                  if (isfillormix)                                  if (isfillormix)
# Line 108  bitmap_decompress(unsigned char *output, Line 127  bitmap_decompress(unsigned char *output,
127                                  count <<= 3;                                  count <<= 3;
128                          }                          }
129                  }                  }
   
130                  /* Read preliminary data */                  /* Read preliminary data */
131                  switch (opcode)                  switch (opcode)
132                  {                  {
# Line 136  bitmap_decompress(unsigned char *output, Line 154  bitmap_decompress(unsigned char *output,
154                                  opcode = 0x02;                                  opcode = 0x02;
155                                  fom_mask = 5;                                  fom_mask = 5;
156                                  break;                                  break;
   
157                  }                  }
   
158                  lastopcode = opcode;                  lastopcode = opcode;
159                  mixmask = 0;                  mixmask = 0;
   
160                  /* Output body */                  /* Output body */
161                  while (count > 0)                  while (count > 0)
162                  {                  {
# Line 149  bitmap_decompress(unsigned char *output, Line 164  bitmap_decompress(unsigned char *output,
164                          {                          {
165                                  if (height <= 0)                                  if (height <= 0)
166                                          return False;                                          return False;
   
167                                  x = 0;                                  x = 0;
168                                  height--;                                  height--;
   
169                                  prevline = line;                                  prevline = line;
170                                  line = output + height * width;                                  line = output + height * width;
171                          }                          }
   
172                          switch (opcode)                          switch (opcode)
173                          {                          {
174                                  case 0: /* Fill */                                  case 0: /* Fill */
# Line 166  bitmap_decompress(unsigned char *output, Line 178  bitmap_decompress(unsigned char *output,
178                                                          line[x] = mix;                                                          line[x] = mix;
179                                                  else                                                  else
180                                                          line[x] = prevline[x] ^ mix;                                                          line[x] = prevline[x] ^ mix;
   
181                                                  insertmix = False;                                                  insertmix = False;
182                                                  count--;                                                  count--;
183                                                  x++;                                                  x++;
184                                          }                                          }
   
185                                          if (prevline == NULL)                                          if (prevline == NULL)
186                                          {                                          {
187                                                  REPEAT(line[x] = 0);                                                  REPEAT(line[x] = 0)
188                                          }                                          }
189                                          else                                          else
190                                          {                                          {
191                                                  REPEAT(line[x] = prevline[x]);                                                  REPEAT(line[x] = prevline[x])
192                                          }                                          }
193                                          break;                                          break;
   
194                                  case 1: /* Mix */                                  case 1: /* Mix */
195                                          if (prevline == NULL)                                          if (prevline == NULL)
196                                          {                                          {
197                                                  REPEAT(line[x] = mix);                                                  REPEAT(line[x] = mix)
198                                          }                                          }
199                                          else                                          else
200                                          {                                          {
201                                                  REPEAT(line[x] = prevline[x] ^ mix);                                                  REPEAT(line[x] = prevline[x] ^ mix)
202                                          }                                          }
203                                          break;                                          break;
   
204                                  case 2: /* Fill or Mix */                                  case 2: /* Fill or Mix */
205                                          if (prevline == NULL)                                          if (prevline == NULL)
206                                          {                                          {
207                                                  REPEAT(MASK_UPDATE();                                                  REPEAT
208                                                         if (mask & mixmask) line[x] = mix;                                                  (
209                                                         else                                                          MASK_UPDATE();
210                                                         line[x] = 0;);                                                          if (mask & mixmask)
211                                                                    line[x] = mix;
212                                                            else
213                                                                    line[x] = 0;
214                                                    )
215                                          }                                          }
216                                          else                                          else
217                                          {                                          {
218                                                  REPEAT(MASK_UPDATE();                                                  REPEAT
219                                                         if (mask & mixmask)                                                  (
220                                                         line[x] = prevline[x] ^ mix;                                                          MASK_UPDATE();
221                                                         else                                                          if (mask & mixmask)
222                                                         line[x] = prevline[x];);                                                                  line[x] = prevline[x] ^ mix;
223                                                            else
224                                                                    line[x] = prevline[x];
225                                                    )
226                                          }                                          }
227                                          break;                                          break;
   
228                                  case 3: /* Colour */                                  case 3: /* Colour */
229                                          REPEAT(line[x] = colour2);                                          REPEAT(line[x] = colour2)
230                                          break;                                          break;
   
231                                  case 4: /* Copy */                                  case 4: /* Copy */
232                                          REPEAT(line[x] = CVAL(input));                                          REPEAT(line[x] = CVAL(input))
233                                          break;                                          break;
   
234                                  case 8: /* Bicolour */                                  case 8: /* Bicolour */
235                                          REPEAT(if (bicolour)                                          REPEAT
236                                                 {                                          (
237                                                 line[x] = colour2; bicolour = False;}                                                  if (bicolour)
238                                                 else                                                  {
239                                                 {                                                          line[x] = colour2;
240                                                 line[x] = colour1; bicolour = True; count++;}                                                          bicolour = False;
241                                          );                                                  }
242                                                    else
243                                                    {
244                                                            line[x] = colour1;
245                                                            bicolour = True; count++;
246                                                    }
247                                            )
248                                          break;                                          break;
   
249                                  case 0xd:       /* White */                                  case 0xd:       /* White */
250                                          REPEAT(line[x] = 0xff);                                          REPEAT(line[x] = 0xff)
251                                          break;                                          break;
   
252                                  case 0xe:       /* Black */                                  case 0xe:       /* Black */
253                                          REPEAT(line[x] = 0x00);                                          REPEAT(line[x] = 0)
254                                          break;                                          break;
255                                    default:
256                                            unimpl("bitmap opcode 0x%x\n", opcode);
257                                            return False;
258                            }
259                    }
260            }
261            return True;
262    }
263    
264    /* 2 byte bitmap decompress */
265    static RD_BOOL
266    bitmap_decompress2(uint8 * output, int width, int height, uint8 * input, int size)
267    {
268            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            while (input < end)
279            {
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:                                  default:
455                                          unimpl("bitmap opcode 0x%x\n", opcode);                                          unimpl("bitmap opcode 0x%x\n", opcode);
456                                          return False;                                          return False;
457                          }                          }
458                  }                  }
459          }          }
460            return True;
461    }
462    
463    /* 3 byte bitmap decompress */
464    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            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            }
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    /* 4 byte bitmap decompress */
856    static RD_BOOL
857    bitmap_decompress4(uint8 * output, int width, int height, uint8 * input, int size)
858    {
859            int code;
860            int bytes_pro;
861            int total_pro;
862    
863            code = CVAL(input);
864            if (code != 0x10)
865            {
866                    return False;
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    /* 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            switch (Bpp)
890            {
891                    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    
910    /* *INDENT-ON* */

Legend:
Removed from v.207  
changed lines
  Added in v.1417

  ViewVC Help
Powered by ViewVC 1.1.26