"Fossies" - the Fresh Open Source Software Archive

Member "rdesktop-1.9.0/bitmap.c" (13 Jun 2019, 18263 Bytes) of package /linux/privat/rdesktop-1.9.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "bitmap.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.8.3_vs_1.8.5.

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