/[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 649 by jsorg71, Thu Apr 15 17:28:30 2004 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
# Line 18  Line 18 
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 */  /* three seperate function for speed when decompressing the bitmaps
22  /* when modifing one function make the change in the others */     when modifing one function make the change in the others
23  /* comment out #define BITMAP_SPEED_OVER_SIZE below for one slower function */     jay.sorg@gmail.com */
 /* j@american-data.com */  
   
 #define BITMAP_SPEED_OVER_SIZE  
24    
25  /* indent is confused by this file */  /* indent is confused by this file */
26  /* *INDENT-OFF* */  /* *INDENT-OFF* */
# Line 31  Line 28 
28  #include "rdesktop.h"  #include "rdesktop.h"
29    
30  #define CVAL(p)   (*(p++))  #define CVAL(p)   (*(p++))
31  #define CVAL2(p)   (*(((uint16*)p)++)) /* for 16 bit */  #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 58  Line 63 
63          } \          } \
64  }  }
65    
 #ifdef BITMAP_SPEED_OVER_SIZE  
   
66  /* 1 byte bitmap decompress */  /* 1 byte bitmap decompress */
67  static BOOL  static RD_BOOL
68  bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size)  bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size)
69  {  {
70          uint8 *end = input + size;          uint8 *end = input + size;
# Line 259  bitmap_decompress1(uint8 * output, int w Line 262  bitmap_decompress1(uint8 * output, int w
262  }  }
263    
264  /* 2 byte bitmap decompress */  /* 2 byte bitmap decompress */
265  static BOOL  static RD_BOOL
266  bitmap_decompress2(uint8 * output, int width, int height, uint8 * input, int size)  bitmap_decompress2(uint8 * output, int width, int height, uint8 * input, int size)
267  {  {
268          uint8 *end = input + size;          uint8 *end = input + size;
# Line 330  bitmap_decompress2(uint8 * output, int w Line 333  bitmap_decompress2(uint8 * output, int w
333                                          insertmix = True;                                          insertmix = True;
334                                  break;                                  break;
335                          case 8: /* Bicolour */                          case 8: /* Bicolour */
336                                  colour1 = CVAL2(input);                                  CVAL2(input, colour1);
337                          case 3: /* Colour */                          case 3: /* Colour */
338                                  colour2 = CVAL2(input);                                  CVAL2(input, colour2);
339                                  break;                                  break;
340                          case 6: /* SetMix/Mix */                          case 6: /* SetMix/Mix */
341                          case 7: /* SetMix/FillOrMix */                          case 7: /* SetMix/FillOrMix */
342                                  mix = CVAL2(input);                                  CVAL2(input, mix);
343                                  opcode -= 5;                                  opcode -= 5;
344                                  break;                                  break;
345                          case 9: /* FillOrMix_1 */                          case 9: /* FillOrMix_1 */
# Line 424  bitmap_decompress2(uint8 * output, int w Line 427  bitmap_decompress2(uint8 * output, int w
427                                          REPEAT(line[x] = colour2)                                          REPEAT(line[x] = colour2)
428                                          break;                                          break;
429                                  case 4: /* Copy */                                  case 4: /* Copy */
430                                          REPEAT(line[x] = CVAL2(input))                                          REPEAT(CVAL2(input, line[x]))
431                                          break;                                          break;
432                                  case 8: /* Bicolour */                                  case 8: /* Bicolour */
433                                          REPEAT                                          REPEAT
# Line 458  bitmap_decompress2(uint8 * output, int w Line 461  bitmap_decompress2(uint8 * output, int w
461  }  }
462    
463  /* 3 byte bitmap decompress */  /* 3 byte bitmap decompress */
464  static BOOL  static RD_BOOL
465  bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int size)  bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int size)
466  {  {
467          uint8 *end = input + size;          uint8 *end = input + size;
# Line 743  bitmap_decompress3(uint8 * output, int w Line 746  bitmap_decompress3(uint8 * output, int w
746          return True;          return True;
747  }  }
748    
749  #else  /* decompress a colour plane */
750    static int
751  static uint32  process_plane(uint8 * in, int width, int height, uint8 * out, int size)
 cvalx(uint8 **input, int Bpp)  
 {  
         uint32 rv = 0;  
         memcpy(&rv, *input, Bpp);  
         *input += Bpp;  
         return rv;  
 }  
   
 static void  
 setli(uint8 *input, int offset, uint32 value, int Bpp)  
 {  
         input += offset * Bpp;  
         memcpy(input, &value, Bpp);  
 }  
   
 static uint32  
 getli(uint8 *input, int offset, int Bpp)  
 {  
         uint32 rv = 0;  
         input += offset * Bpp;  
         memcpy(&rv, input, Bpp);  
         return rv;  
 }  
   
 static BOOL  
 bitmap_decompressx(uint8 *output, int width, int height, uint8 *input, int size, int Bpp)  
752  {  {
753          uint8 *end = input + size;          int indexw;
754          uint8 *prevline = NULL, *line = NULL;          int indexh;
755          int opcode, count, offset, isfillormix, x = width;          int code;
756          int lastopcode = -1, insertmix = False, bicolour = False;          int collen;
757          uint8 code;          int replen;
758          uint32 colour1 = 0, colour2 = 0;          int color;
759          uint8 mixmask, mask = 0;          int x;
760          uint32 mix = 0xffffffff;          int revcode;
761          int fom_mask = 0;          uint8 * last_line;
762            uint8 * this_line;
763          while (input < end)          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                  fom_mask = 0;                  out = (org_out + width * height * 4) - ((indexh + 1) * width * 4);
773                  code = CVAL(input);                  color = 0;
774                  opcode = code >> 4;                  this_line = out;
775                    indexw = 0;
776                  /* Handle different opcode forms */                  if (last_line == 0)
777                  switch (opcode)                  {
778                  {                          while (indexw < width)
779                          case 0xc:                          {
780                          case 0xd:                                  code = CVAL(in);
781                          case 0xe:                                  replen = code & 0xf;
782                                  opcode -= 6;                                  collen = (code >> 4) & 0xf;
783                                  count = code & 0xf;                                  revcode = (replen << 4) | collen;
784                                  offset = 16;                                  if ((revcode <= 47) && (revcode >= 16))
                                 break;  
   
                         case 0xf:  
                                 opcode = code & 0xf;  
                                 if (opcode < 9)  
785                                  {                                  {
786                                          count = CVAL(input);                                          replen = revcode;
787                                          count |= CVAL(input) << 8;                                          collen = 0;
788                                  }                                  }
789                                  else                                  while (collen > 0)
790                                  {                                  {
791                                          count = (opcode < 0xb) ? 8 : 1;                                          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                                  }                                  }
                                 offset = 0;  
                                 break;  
   
                         default:  
                                 opcode >>= 1;  
                                 count = code & 0x1f;  
                                 offset = 32;  
                                 break;  
                 }  
   
                 /* Handle strange cases for counts */  
                 if (offset != 0)  
                 {  
                         isfillormix = ((opcode == 2) || (opcode == 7));  
   
                         if (count == 0)  
                         {  
                                 if (isfillormix)  
                                         count = CVAL(input) + 1;  
                                 else  
                                         count = CVAL(input) + offset;  
                         }  
                         else if (isfillormix)  
                         {  
                                 count <<= 3;  
804                          }                          }
805                  }                  }
806                    else
                 /* Read preliminary data */  
                 switch (opcode)  
                 {  
                         case 0: /* Fill */  
                                 if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))  
                                         insertmix = True;  
                                 break;  
                         case 8: /* Bicolour */  
                                 colour1 = cvalx(&input, Bpp);  
                         case 3: /* Colour */  
                                 colour2 = cvalx(&input, Bpp);  
                                 break;  
                         case 6: /* SetMix/Mix */  
                         case 7: /* SetMix/FillOrMix */  
                                 mix = cvalx(&input, Bpp);  
                                 opcode -= 5;  
                                 break;  
                         case 9: /* FillOrMix_1 */  
                                 mask = 0x03;  
                                 opcode = 0x02;  
                                 fom_mask = 3;  
                                 break;  
                         case 0x0a:      /* FillOrMix_2 */  
                                 mask = 0x05;  
                                 opcode = 0x02;  
                                 fom_mask = 5;  
                                 break;  
   
                 }  
   
                 lastopcode = opcode;  
                 mixmask = 0;  
   
                 /* Output body */  
                 while (count > 0)  
807                  {                  {
808                          if (x >= width)                          while (indexw < width)
809                          {                          {
810                                  if (height <= 0)                                  code = CVAL(in);
811                                          return False;                                  replen = code & 0xf;
812                                    collen = (code >> 4) & 0xf;
813                                  x = 0;                                  revcode = (replen << 4) | collen;
814                                  height--;                                  if ((revcode <= 47) && (revcode >= 16))
815                                    {
816                                  prevline = line;                                          replen = revcode;
817                                  line = output + height * width * Bpp;                                          collen = 0;
818                          }                                  }
819                                    while (collen > 0)
820                          switch (opcode)                                  {
821                          {                                          x = CVAL(in);
822                                  case 0: /* Fill */                                          if (x & 1)
                                         if (insertmix)  
                                         {  
                                                 if (prevline == NULL)  
                                                         setli(line, x, mix, Bpp);  
                                                 else  
                                                         setli(line, x,  
                                                               getli(prevline, x, Bpp) ^ mix, Bpp);  
   
                                                 insertmix = False;  
                                                 count--;  
                                                 x++;  
                                         }  
   
                                         if (prevline == NULL)  
                                         {  
                                         REPEAT(setli(line, x, 0, Bpp))}  
                                         else  
                                         {  
                                                 REPEAT(setli  
                                                        (line, x, getli(prevline, x, Bpp), Bpp));  
                                         }  
                                         break;  
   
                                 case 1: /* Mix */  
                                         if (prevline == NULL)  
                                         {  
                                                 REPEAT(setli(line, x, mix, Bpp));  
                                         }  
                                         else  
                                         {  
                                                 REPEAT(setli  
                                                        (line, x, getli(prevline, x, Bpp) ^ mix,  
                                                         Bpp));  
                                         }  
                                         break;  
   
                                 case 2: /* Fill or Mix */  
                                         if (prevline == NULL)  
823                                          {                                          {
824                                                  REPEAT(MASK_UPDATE();                                                  x = x >> 1;
825                                                         if (mask & mixmask) setli(line, x, mix, Bpp);                                                  x = x + 1;
826                                                         else                                                  color = -x;
                                                        setli(line, x, 0, Bpp););  
827                                          }                                          }
828                                          else                                          else
829                                          {                                          {
830                                                  REPEAT(MASK_UPDATE();                                                  x = x >> 1;
831                                                         if (mask & mixmask)                                                  color = x;
                                                        setli(line, x, getli(prevline, x, Bpp) ^ mix,  
                                                              Bpp);  
                                                        else  
                                                        setli(line, x, getli(prevline, x, Bpp),  
                                                              Bpp););  
832                                          }                                          }
833                                          break;                                          x = last_line[indexw * 4] + color;
834                                            *out = x;
835                                  case 3: /* Colour */                                          out += 4;
836                                          REPEAT(setli(line, x, colour2, Bpp));                                          indexw++;
837                                          break;                                          collen--;
838                                    }
839                                  case 4: /* Copy */                                  while (replen > 0)
840                                          REPEAT(setli(line, x, cvalx(&input, Bpp), Bpp));                                  {
841                                          break;                                          x = last_line[indexw * 4] + color;
842                                            *out = x;
843                                  case 8: /* Bicolour */                                          out += 4;
844                                          REPEAT(if (bicolour)                                          indexw++;
845                                                 {                                          replen--;
846                                                 setli(line, x, colour2, Bpp); bicolour = False;}                                  }
                                                else  
                                                {  
                                                setli(line, x, colour1, Bpp); bicolour = True;  
                                                count++;}  
                                         );  
                                         break;  
   
                                 case 0xd:       /* White */  
                                         REPEAT(setli(line, x, 0xffffffff, Bpp));  
                                         break;  
   
                                 case 0xe:       /* Black */  
                                         REPEAT(setli(line, x, 0, Bpp));  
                                         break;  
   
                                 default:  
                                         unimpl("bitmap opcode 0x%x\n", opcode);  
                                         return False;  
847                          }                          }
848                  }                  }
849                    indexh++;
850                    last_line = this_line;
851          }          }
852            return (int) (in - org_in);
         return True;  
853  }  }
854    
855  #endif  /* 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 */  /* main decompress function */
884  BOOL  RD_BOOL
885  bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp)  bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp)
886  {  {
887  #ifdef BITMAP_SPEED_OVER_SIZE          RD_BOOL rv = False;
888          BOOL rv = False;  
889          switch (Bpp)          switch (Bpp)
890          {          {
891                  case 1:                  case 1:
# Line 1002  bitmap_decompress(uint8 * output, int wi Line 897  bitmap_decompress(uint8 * output, int wi
897                  case 3:                  case 3:
898                          rv = bitmap_decompress3(output, width, height, input, size);                          rv = bitmap_decompress3(output, width, height, input, size);
899                          break;                          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          }          }
 #else  
         BOOL rv;  
   rv = bitmap_decompressx(output, width, height, input, size, Bpp);  
 #endif  
907          return rv;          return rv;
908  }  }
909    

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

  ViewVC Help
Powered by ViewVC 1.1.26