diff options
Diffstat (limited to 'libxrdp/xrdp_bitmap32_compress.c')
| -rw-r--r-- | libxrdp/xrdp_bitmap32_compress.c | 222 | 
1 files changed, 209 insertions, 13 deletions
| diff --git a/libxrdp/xrdp_bitmap32_compress.c b/libxrdp/xrdp_bitmap32_compress.c index 6af7ed75..c3afff90 100644 --- a/libxrdp/xrdp_bitmap32_compress.c +++ b/libxrdp/xrdp_bitmap32_compress.c @@ -26,6 +26,173 @@ http://msdn.microsoft.com/en-us/library/cc241877.aspx  #include "libxrdp.h" +#define FLAGS_RLE     0x10 +#define FLAGS_NOALPHA 0x20 + +#define LLOG_LEVEL 1 +#define LLOGLN(_level, _args) \ +  do { if (_level < LLOG_LEVEL) { g_writeln _args ; } } while (0) +#define LHEXDUMP(_level, _args) \ +  do { if (_level < LLOG_LEVEL) { g_hexdump _args ; } } while (0) + +/*****************************************************************************/ +static int APP_CC +fdelta(char *plane, int cx, int cy) +{ +    char delta; +    char *ptr8; +    int index; +    int jndex; + +    for (jndex = cy - 2; jndex >= 0; jndex--) +    { +        ptr8 = plane + jndex * cx; +        for (index = 0; index < cx; index++) +        { +            delta = ptr8[cx] - ptr8[0]; +            if (delta & 0x80) +            { +                delta = (((~delta) + 1) << 1) - 1; +            } +            else +            { +                delta = delta << 1; +            } +            ptr8[cx] = delta; +            ptr8++; +        } +    } +    return 0; +} + +/*****************************************************************************/ +static int APP_CC +fout(int collen, int replen, char *colptr, struct stream *s) +{ +    int code; +    int lcollen; +    int lreplen; +    int cont; + +    LLOGLN(10, ("fout: collen %d replen %d", collen, replen)); +    cont = collen > 13; +    while (cont) +    { +        lcollen = collen; +        if (lcollen > 15) +        { +            lcollen = 15; +        } +        code = lcollen << 4; +        out_uint8(s, code); +        out_uint8a(s, colptr, lcollen); +        colptr += lcollen; +        collen -= lcollen; +        cont = collen > 13; +    } +    cont = (collen > 0) || (replen > 0); +    while (cont) +    { +        lreplen = replen; +        if ((collen == 0) && (lreplen > 15)) +        { +            /* big run */ +            if (lreplen > 47) +            { +                lreplen = 47; +            } +            LLOGLN(10, ("fout: big run lreplen %d", lreplen)); +            replen -= lreplen; +            code = ((lreplen & 0xF) << 4) | ((lreplen & 0xF0) >> 4); +        } +        else +        { +            if (lreplen > 15) +            { +                lreplen = 15; +            } +            replen -= lreplen; +            if (lreplen < 3) +            { +                collen += lreplen; +                lreplen = 0; +            } +            code = (collen << 4) | lreplen; +        } +        out_uint8(s, code); +        out_uint8a(s, colptr, collen); +        colptr += collen + lreplen; +        collen = 0; +        cont = replen > 0; +    } +    return 0; +} + +/*****************************************************************************/ +static int APP_CC +fpack(char *plane, int cx, int cy, struct stream *s) +{ +    char *ptr8; +    char *colptr; +    char *lend; +    int jndex; +    int collen; +    int replen; + +    LLOGLN(10, ("fpack:")); +    for (jndex = 0; jndex < cy; jndex++) +    { +        LLOGLN(10, ("line start line %d cx %d cy %d", jndex, cx, cy)); +        ptr8 = plane + jndex * cx; +        LHEXDUMP(10, (ptr8, cx)); +        lend = ptr8 + (cx - 1); +        colptr = ptr8; +        if (colptr[0] == 0) +        { +            collen = 0; +            replen = 1; +        } +        else +        { +            collen = 1; +            replen = 0; +        } +        while (ptr8 < lend) +        { +            if (ptr8[0] == ptr8[1]) +            { +                replen++; +            } +            else +            { +                if (replen > 0) +                { +                    if (replen < 3) +                    { +                        collen += replen + 1; +                        replen = 0; +                    } +                    else +                    { +                        fout(collen, replen, colptr, s); +                        colptr = ptr8 + 1; +                        replen = 0; +                        collen = 1; +                    } +                } +                else +                { +                    collen++; +                } +            } +            ptr8++; +        } +        /* end of line */ +        fout(collen, replen, colptr, s); +    } +    return 0; +} +  /*****************************************************************************/  /* returns the number of lines compressed */  int APP_CC @@ -36,7 +203,6 @@ xrdp_bitmap32_compress(char *in_data, int width, int height,  {      int pixel;      int *ptr32; -    char *ptr8;      char *alpha_data;      char *red_data;      char *green_data; @@ -45,17 +211,20 @@ xrdp_bitmap32_compress(char *in_data, int width, int height,      int red_bytes;      int green_bytes;      int blue_bytes; -    int iindex; -    int jindex; +    int index;      int cx;      int cy;      int header; -    header = 0x20; /* no alpha TODO */ +    LLOGLN(10, ("xrdp_bitmap32_compress:")); + +    //header = FLAGS_NOALPHA | FLAGS_RLE; +    //header = FLAGS_NOALPHA; +    header = FLAGS_RLE;      cx = width + e;      cy = 0; -    alpha_data = g_malloc(cx * height * 4, 0); +    alpha_data = temp_s->data;      red_data = alpha_data + cx * height;      green_data = red_data + cx * height;      blue_data = green_data + cx * height; @@ -68,7 +237,7 @@ xrdp_bitmap32_compress(char *in_data, int width, int height,      while (start_line >= 0)      {          ptr32 = (int *) (in_data + start_line * width * 4); -        for (iindex = 0; iindex < width; iindex++) +        for (index = 0; index < width; index++)          {              pixel = *ptr32;              ptr32++; @@ -81,7 +250,7 @@ xrdp_bitmap32_compress(char *in_data, int width, int height,              blue_data[blue_bytes] = pixel >> 0;              blue_bytes++;          } -        for (iindex = 0; iindex < e; iindex++) +        for (index = 0; index < e; index++)          {              alpha_data[alpha_bytes] = 0;              alpha_bytes++; @@ -95,15 +264,42 @@ xrdp_bitmap32_compress(char *in_data, int width, int height,          start_line--;          cy++;      } -    out_uint8(s, header); -    out_uint8a(s, red_data, red_bytes); -    out_uint8a(s, green_data, green_bytes); -    out_uint8a(s, blue_data, blue_bytes); -    if ((header & 0x10) == 0) + +    if (header & FLAGS_RLE)      { +        out_uint8(s, header); + +        /* delta, other steps */ +        if ((header & FLAGS_NOALPHA) == 0) +        { +            fdelta(alpha_data, cx, cy); +        } +        fdelta(red_data, cx, cy); +        fdelta(green_data, cx, cy); +        fdelta(blue_data, cx, cy); + +        /* pack */ +        if ((header & FLAGS_NOALPHA) == 0) +        { +            fpack(alpha_data, cx, cy, s); +        } +        fpack(red_data, cx, cy, s); +        fpack(green_data, cx, cy, s); +        fpack(blue_data, cx, cy, s); +    } +    else +    { +        out_uint8(s, header); +        if ((header & FLAGS_NOALPHA) == 0) +        { +            out_uint8a(s, alpha_data, alpha_bytes); +        } +        out_uint8a(s, red_data, red_bytes); +        out_uint8a(s, green_data, green_bytes); +        out_uint8a(s, blue_data, blue_bytes);          /* pad if no RLE */          out_uint8(s, 0x00);      } -    g_free(alpha_data); +      return cy;  } | 
