Projects STRLCPY aardwolf Commits 056fd7b2
🤬
  • ■ ■ ■ ■
    aardwolf/_version.py
    1 1   
    2  -__version__ = "0.1.1"
     2 +__version__ = "0.2.0"
    3 3  __banner__ = \
    4 4  """
    5 5  # aardwolf %s
    skipped 2 lines
  • aardwolf/connection.py
    Content is identical
  • aardwolf/develstuff/pertest.py
    Unable to diff as some line is too long.
  • ■ ■ ■ ■ ■
    aardwolf/utils/rectconvert.py
    1  -from ast import Import
    2  -import io
    3  -import rle
     1 +import librlers
    4 2  from PIL import Image
    5  - 
    6  -from aardwolf.commons.queuedata.constants import VIDEO_FORMAT
    7  - 
    8 3   
    9 4  bpp_2_bytes = {
    10  - 15: 2,
    11 5   16: 2,
    12 6   24: 3,
    13 7   32: 4,
    skipped 2 lines
    16 10  def rectconvert(width, height, bitsPerPixel, isCompress, data):
    17 11   if bitsPerPixel not in bpp_2_bytes:
    18 12   raise ValueError("bitsPerPixel value of %s is not supported!" % bitsPerPixel)
    19  - image = bytes(width * height * 4)
    20  - rle.bitmap_decompress(image, width, height, data, bitsPerPixel, bpp_2_bytes[bitsPerPixel], int(isCompress))
    21  - return Image.frombytes('RGBA', [width, height], image)
     13 + image = librlers.bitmap_decompress(data, width, height, 16, int(isCompress))
     14 + return Image.frombytes('RGBA', [width, height], bytes(image))
  • ■ ■ ■ ■ ■ ■
    aardwolf/utils/rle/rle.c
    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  -/*
    21  -Added few modifications:
    22  -The code now ALWAYS returns RGB32 format regardless of input bpp. Makes life easier on upper levels.
    23  -The code also takes non-compressed input (and a flag that indicates wether it's compressed or not.)
    24  -Non-compressed data will be only converted to RGB32.
    25  -There are some out-of-bounds write possibilities in the RRE decoder.
    26  - 
    27  -Mod author: Tamas Jos @skelsec
    28  -*/
    29  - 
    30  -/* three seperate function for speed when decompressing the bitmaps
    31  - when modifing one function make the change in the others
    32  - [email protected] */
    33  - 
    34  -/* indent is confused by this file */
    35  -/* *INDENT-OFF* */
    36  - 
    37  -#include <stdlib.h>
    38  -#include <Python.h>
    39  - 
    40  -/* Specific rename for RDPY integration */
    41  -#define uint8 unsigned char
    42  -#define uint16 unsigned short
    43  -#define uint unsigned int
    44  -#define unimpl(str, code)
    45  - 
    46  -#define RD_BOOL int
    47  -#define False 0
    48  -#define True 1
    49  -/* end specific rename */
    50  - 
    51  -#define CVAL(p) (*(p++))
    52  -#ifdef NEED_ALIGN
    53  -#ifdef L_ENDIAN
    54  -#define CVAL2(p, v) { v = (*(p++)); v |= (*(p++)) << 8; }
    55  -#else
    56  -#define CVAL2(p, v) { v = (*(p++)) << 8; v |= (*(p++)); }
    57  -#endif /* L_ENDIAN */
    58  -#else
    59  -#define CVAL2(p, v) { v = (*((uint16*)p)); p += 2; }
    60  -#endif /* NEED_ALIGN */
    61  - 
    62  -#define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
    63  - 
    64  -#define REPEAT(statement) \
    65  -{ \
    66  - while((count & ~0x7) && ((x+8) < width)) \
    67  - UNROLL8( statement; count--; x++; ); \
    68  - \
    69  - while((count > 0) && (x < width)) \
    70  - { \
    71  - statement; \
    72  - count--; \
    73  - x++; \
    74  - } \
    75  -}
    76  - 
    77  -#define MASK_UPDATE() \
    78  -{ \
    79  - mixmask <<= 1; \
    80  - if (mixmask == 0) \
    81  - { \
    82  - mask = fom_mask ? fom_mask : CVAL(input); \
    83  - mixmask = 1; \
    84  - } \
    85  -}
    86  - 
    87  -/* 1 byte bitmap decompress */
    88  -static RD_BOOL
    89  -bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size)
    90  -{
    91  - uint8 *end = input + size;
    92  - uint8 *prevline = NULL, *line = NULL;
    93  - int opcode, count, offset, isfillormix, x = width;
    94  - int lastopcode = -1, insertmix = False, bicolour = False;
    95  - uint8 code;
    96  - uint8 colour1 = 0, colour2 = 0;
    97  - uint8 mixmask, mask = 0;
    98  - uint8 mix = 0xff;
    99  - int fom_mask = 0;
    100  - 
    101  - while (input < end)
    102  - {
    103  - fom_mask = 0;
    104  - code = CVAL(input);
    105  - opcode = code >> 4;
    106  - /* Handle different opcode forms */
    107  - switch (opcode)
    108  - {
    109  - case 0xc:
    110  - case 0xd:
    111  - case 0xe:
    112  - opcode -= 6;
    113  - count = code & 0xf;
    114  - offset = 16;
    115  - break;
    116  - case 0xf:
    117  - opcode = code & 0xf;
    118  - if (opcode < 9)
    119  - {
    120  - count = CVAL(input);
    121  - count |= CVAL(input) << 8;
    122  - }
    123  - else
    124  - {
    125  - count = (opcode < 0xb) ? 8 : 1;
    126  - }
    127  - offset = 0;
    128  - break;
    129  - default:
    130  - opcode >>= 1;
    131  - count = code & 0x1f;
    132  - offset = 32;
    133  - break;
    134  - }
    135  - /* Handle strange cases for counts */
    136  - if (offset != 0)
    137  - {
    138  - isfillormix = ((opcode == 2) || (opcode == 7));
    139  - if (count == 0)
    140  - {
    141  - if (isfillormix)
    142  - count = CVAL(input) + 1;
    143  - else
    144  - count = CVAL(input) + offset;
    145  - }
    146  - else if (isfillormix)
    147  - {
    148  - count <<= 3;
    149  - }
    150  - }
    151  - /* Read preliminary data */
    152  - switch (opcode)
    153  - {
    154  - case 0: /* Fill */
    155  - if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
    156  - insertmix = True;
    157  - break;
    158  - case 8: /* Bicolour */
    159  - colour1 = CVAL(input);
    160  - case 3: /* Colour */
    161  - colour2 = CVAL(input);
    162  - break;
    163  - case 6: /* SetMix/Mix */
    164  - case 7: /* SetMix/FillOrMix */
    165  - mix = CVAL(input);
    166  - opcode -= 5;
    167  - break;
    168  - case 9: /* FillOrMix_1 */
    169  - mask = 0x03;
    170  - opcode = 0x02;
    171  - fom_mask = 3;
    172  - break;
    173  - case 0x0a: /* FillOrMix_2 */
    174  - mask = 0x05;
    175  - opcode = 0x02;
    176  - fom_mask = 5;
    177  - break;
    178  - }
    179  - lastopcode = opcode;
    180  - mixmask = 0;
    181  - /* Output body */
    182  - while (count > 0)
    183  - {
    184  - if (x >= width)
    185  - {
    186  - if (height <= 0)
    187  - return False;
    188  - x = 0;
    189  - height--;
    190  - prevline = line;
    191  - line = output + height * width;
    192  - }
    193  - switch (opcode)
    194  - {
    195  - case 0: /* Fill */
    196  - if (insertmix)
    197  - {
    198  - if (prevline == NULL)
    199  - line[x] = mix;
    200  - else
    201  - line[x] = prevline[x] ^ mix;
    202  - insertmix = False;
    203  - count--;
    204  - x++;
    205  - }
    206  - if (prevline == NULL)
    207  - {
    208  - REPEAT(line[x] = 0)
    209  - }
    210  - else
    211  - {
    212  - REPEAT(line[x] = prevline[x])
    213  - }
    214  - break;
    215  - case 1: /* Mix */
    216  - if (prevline == NULL)
    217  - {
    218  - REPEAT(line[x] = mix)
    219  - }
    220  - else
    221  - {
    222  - REPEAT(line[x] = prevline[x] ^ mix)
    223  - }
    224  - break;
    225  - case 2: /* Fill or Mix */
    226  - if (prevline == NULL)
    227  - {
    228  - REPEAT
    229  - (
    230  - MASK_UPDATE();
    231  - if (mask & mixmask)
    232  - line[x] = mix;
    233  - else
    234  - line[x] = 0;
    235  - )
    236  - }
    237  - else
    238  - {
    239  - REPEAT
    240  - (
    241  - MASK_UPDATE();
    242  - if (mask & mixmask)
    243  - line[x] = prevline[x] ^ mix;
    244  - else
    245  - line[x] = prevline[x];
    246  - )
    247  - }
    248  - break;
    249  - case 3: /* Colour */
    250  - REPEAT(line[x] = colour2)
    251  - break;
    252  - case 4: /* Copy */
    253  - REPEAT(line[x] = CVAL(input))
    254  - break;
    255  - case 8: /* Bicolour */
    256  - REPEAT
    257  - (
    258  - if (bicolour)
    259  - {
    260  - line[x] = colour2;
    261  - bicolour = False;
    262  - }
    263  - else
    264  - {
    265  - line[x] = colour1;
    266  - bicolour = True; count++;
    267  - }
    268  - )
    269  - break;
    270  - case 0xd: /* White */
    271  - REPEAT(line[x] = 0xff)
    272  - break;
    273  - case 0xe: /* Black */
    274  - REPEAT(line[x] = 0)
    275  - break;
    276  - default:
    277  - unimpl("bitmap opcode 0x%x\n", opcode);
    278  - return False;
    279  - }
    280  - }
    281  - }
    282  - return True;
    283  -}
    284  - 
    285  -/* 2 byte bitmap decompress */
    286  -static RD_BOOL
    287  -bitmap_decompress2(uint8 * output, int width, int height, uint8 * input, int size)
    288  -{
    289  - uint8 *end = input + size;
    290  - uint16 *prevline = NULL, *line = NULL;
    291  - int opcode, count, offset, isfillormix, x = width;
    292  - int lastopcode = -1, insertmix = False, bicolour = False;
    293  - uint8 code;
    294  - uint16 colour1 = 0, colour2 = 0;
    295  - uint8 mixmask, mask = 0;
    296  - uint16 mix = 0xffff;
    297  - int fom_mask = 0;
    298  - 
    299  - while (input < end)
    300  - {
    301  - fom_mask = 0;
    302  - code = CVAL(input);
    303  - opcode = code >> 4;
    304  - /* Handle different opcode forms */
    305  - switch (opcode)
    306  - {
    307  - case 0xc:
    308  - case 0xd:
    309  - case 0xe:
    310  - opcode -= 6;
    311  - count = code & 0xf;
    312  - offset = 16;
    313  - break;
    314  - case 0xf:
    315  - opcode = code & 0xf;
    316  - if (opcode < 9)
    317  - {
    318  - count = CVAL(input);
    319  - count |= CVAL(input) << 8;
    320  - }
    321  - else
    322  - {
    323  - count = (opcode < 0xb) ? 8 : 1;
    324  - }
    325  - offset = 0;
    326  - break;
    327  - default:
    328  - opcode >>= 1;
    329  - count = code & 0x1f;
    330  - offset = 32;
    331  - break;
    332  - }
    333  - /* Handle strange cases for counts */
    334  - if (offset != 0)
    335  - {
    336  - isfillormix = ((opcode == 2) || (opcode == 7));
    337  - if (count == 0)
    338  - {
    339  - if (isfillormix)
    340  - count = CVAL(input) + 1;
    341  - else
    342  - count = CVAL(input) + offset;
    343  - }
    344  - else if (isfillormix)
    345  - {
    346  - count <<= 3;
    347  - }
    348  - }
    349  - /* Read preliminary data */
    350  - switch (opcode)
    351  - {
    352  - case 0: /* Fill */
    353  - if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
    354  - insertmix = True;
    355  - break;
    356  - case 8: /* Bicolour */
    357  - CVAL2(input, colour1);
    358  - case 3: /* Colour */
    359  - CVAL2(input, colour2);
    360  - break;
    361  - case 6: /* SetMix/Mix */
    362  - case 7: /* SetMix/FillOrMix */
    363  - CVAL2(input, mix);
    364  - opcode -= 5;
    365  - break;
    366  - case 9: /* FillOrMix_1 */
    367  - mask = 0x03;
    368  - opcode = 0x02;
    369  - fom_mask = 3;
    370  - break;
    371  - case 0x0a: /* FillOrMix_2 */
    372  - mask = 0x05;
    373  - opcode = 0x02;
    374  - fom_mask = 5;
    375  - break;
    376  - }
    377  - lastopcode = opcode;
    378  - mixmask = 0;
    379  - /* Output body */
    380  - while (count > 0)
    381  - {
    382  - if (x >= width)
    383  - {
    384  - if (height <= 0)
    385  - return False;
    386  - x = 0;
    387  - height--;
    388  - prevline = line;
    389  - line = ((uint16 *) output) + height * width;
    390  - }
    391  - switch (opcode)
    392  - {
    393  - case 0: /* Fill */
    394  - if (insertmix)
    395  - {
    396  - if (prevline == NULL)
    397  - line[x] = mix;
    398  - else
    399  - line[x] = prevline[x] ^ mix;
    400  - insertmix = False;
    401  - count--;
    402  - x++;
    403  - }
    404  - if (prevline == NULL)
    405  - {
    406  - REPEAT(line[x] = 0)
    407  - }
    408  - else
    409  - {
    410  - REPEAT(line[x] = prevline[x])
    411  - }
    412  - break;
    413  - case 1: /* Mix */
    414  - if (prevline == NULL)
    415  - {
    416  - REPEAT(line[x] = mix)
    417  - }
    418  - else
    419  - {
    420  - REPEAT(line[x] = prevline[x] ^ mix)
    421  - }
    422  - break;
    423  - case 2: /* Fill or Mix */
    424  - if (prevline == NULL)
    425  - {
    426  - REPEAT
    427  - (
    428  - MASK_UPDATE();
    429  - if (mask & mixmask)
    430  - line[x] = mix;
    431  - else
    432  - line[x] = 0;
    433  - )
    434  - }
    435  - else
    436  - {
    437  - REPEAT
    438  - (
    439  - MASK_UPDATE();
    440  - if (mask & mixmask)
    441  - line[x] = prevline[x] ^ mix;
    442  - else
    443  - line[x] = prevline[x];
    444  - )
    445  - }
    446  - break;
    447  - case 3: /* Colour */
    448  - REPEAT(line[x] = colour2)
    449  - break;
    450  - case 4: /* Copy */
    451  - REPEAT(CVAL2(input, line[x]))
    452  - break;
    453  - case 8: /* Bicolour */
    454  - REPEAT
    455  - (
    456  - if (bicolour)
    457  - {
    458  - line[x] = colour2;
    459  - bicolour = False;
    460  - }
    461  - else
    462  - {
    463  - line[x] = colour1;
    464  - bicolour = True;
    465  - count++;
    466  - }
    467  - )
    468  - break;
    469  - case 0xd: /* White */
    470  - REPEAT(line[x] = 0xffff)
    471  - break;
    472  - case 0xe: /* Black */
    473  - REPEAT(line[x] = 0)
    474  - break;
    475  - default:
    476  - unimpl("bitmap opcode 0x%x\n", opcode);
    477  - return False;
    478  - }
    479  - }
    480  - }
    481  - return True;
    482  -}
    483  - 
    484  -/* 3 byte bitmap decompress */
    485  -static RD_BOOL
    486  -bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int size)
    487  -{
    488  - uint8 *end = input + size;
    489  - uint8 *prevline = NULL, *line = NULL;
    490  - int opcode, count, offset, isfillormix, x = width;
    491  - int lastopcode = -1, insertmix = False, bicolour = False;
    492  - uint8 code;
    493  - uint8 colour1[3] = {0, 0, 0}, colour2[3] = {0, 0, 0};
    494  - uint8 mixmask, mask = 0;
    495  - uint8 mix[3] = {0xff, 0xff, 0xff};
    496  - int fom_mask = 0;
    497  - 
    498  - while (input < end)
    499  - {
    500  - fom_mask = 0;
    501  - code = CVAL(input);
    502  - opcode = code >> 4;
    503  - /* Handle different opcode forms */
    504  - switch (opcode)
    505  - {
    506  - case 0xc:
    507  - case 0xd:
    508  - case 0xe:
    509  - opcode -= 6;
    510  - count = code & 0xf;
    511  - offset = 16;
    512  - break;
    513  - case 0xf:
    514  - opcode = code & 0xf;
    515  - if (opcode < 9)
    516  - {
    517  - count = CVAL(input);
    518  - count |= CVAL(input) << 8;
    519  - }
    520  - else
    521  - {
    522  - count = (opcode <
    523  - 0xb) ? 8 : 1;
    524  - }
    525  - offset = 0;
    526  - break;
    527  - default:
    528  - opcode >>= 1;
    529  - count = code & 0x1f;
    530  - offset = 32;
    531  - break;
    532  - }
    533  - /* Handle strange cases for counts */
    534  - if (offset != 0)
    535  - {
    536  - isfillormix = ((opcode == 2) || (opcode == 7));
    537  - if (count == 0)
    538  - {
    539  - if (isfillormix)
    540  - count = CVAL(input) + 1;
    541  - else
    542  - count = CVAL(input) + offset;
    543  - }
    544  - else if (isfillormix)
    545  - {
    546  - count <<= 3;
    547  - }
    548  - }
    549  - /* Read preliminary data */
    550  - switch (opcode)
    551  - {
    552  - case 0: /* Fill */
    553  - if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
    554  - insertmix = True;
    555  - break;
    556  - case 8: /* Bicolour */
    557  - colour1[0] = CVAL(input);
    558  - colour1[1] = CVAL(input);
    559  - colour1[2] = CVAL(input);
    560  - case 3: /* Colour */
    561  - colour2[0] = CVAL(input);
    562  - colour2[1] = CVAL(input);
    563  - colour2[2] = CVAL(input);
    564  - break;
    565  - case 6: /* SetMix/Mix */
    566  - case 7: /* SetMix/FillOrMix */
    567  - mix[0] = CVAL(input);
    568  - mix[1] = CVAL(input);
    569  - mix[2] = CVAL(input);
    570  - opcode -= 5;
    571  - break;
    572  - case 9: /* FillOrMix_1 */
    573  - mask = 0x03;
    574  - opcode = 0x02;
    575  - fom_mask = 3;
    576  - break;
    577  - case 0x0a: /* FillOrMix_2 */
    578  - mask = 0x05;
    579  - opcode = 0x02;
    580  - fom_mask = 5;
    581  - break;
    582  - }
    583  - lastopcode = opcode;
    584  - mixmask = 0;
    585  - /* Output body */
    586  - while (count > 0)
    587  - {
    588  - if (x >= width)
    589  - {
    590  - if (height <= 0)
    591  - return False;
    592  - x = 0;
    593  - height--;
    594  - prevline = line;
    595  - line = output + height * (width * 3);
    596  - }
    597  - switch (opcode)
    598  - {
    599  - case 0: /* Fill */
    600  - if (insertmix)
    601  - {
    602  - if (prevline == NULL)
    603  - {
    604  - line[x * 3] = mix[0];
    605  - line[x * 3 + 1] = mix[1];
    606  - line[x * 3 + 2] = mix[2];
    607  - }
    608  - else
    609  - {
    610  - line[x * 3] =
    611  - prevline[x * 3] ^ mix[0];
    612  - line[x * 3 + 1] =
    613  - prevline[x * 3 + 1] ^ mix[1];
    614  - line[x * 3 + 2] =
    615  - prevline[x * 3 + 2] ^ mix[2];
    616  - }
    617  - insertmix = False;
    618  - count--;
    619  - x++;
    620  - }
    621  - if (prevline == NULL)
    622  - {
    623  - REPEAT
    624  - (
    625  - line[x * 3] = 0;
    626  - line[x * 3 + 1] = 0;
    627  - line[x * 3 + 2] = 0;
    628  - )
    629  - }
    630  - else
    631  - {
    632  - REPEAT
    633  - (
    634  - line[x * 3] = prevline[x * 3];
    635  - line[x * 3 + 1] = prevline[x * 3 + 1];
    636  - line[x * 3 + 2] = prevline[x * 3 + 2];
    637  - )
    638  - }
    639  - break;
    640  - case 1: /* Mix */
    641  - if (prevline == NULL)
    642  - {
    643  - REPEAT
    644  - (
    645  - line[x * 3] = mix[0];
    646  - line[x * 3 + 1] = mix[1];
    647  - line[x * 3 + 2] = mix[2];
    648  - )
    649  - }
    650  - else
    651  - {
    652  - REPEAT
    653  - (
    654  - line[x * 3] =
    655  - prevline[x * 3] ^ mix[0];
    656  - line[x * 3 + 1] =
    657  - prevline[x * 3 + 1] ^ mix[1];
    658  - line[x * 3 + 2] =
    659  - prevline[x * 3 + 2] ^ mix[2];
    660  - )
    661  - }
    662  - break;
    663  - case 2: /* Fill or Mix */
    664  - if (prevline == NULL)
    665  - {
    666  - REPEAT
    667  - (
    668  - MASK_UPDATE();
    669  - if (mask & mixmask)
    670  - {
    671  - line[x * 3] = mix[0];
    672  - line[x * 3 + 1] = mix[1];
    673  - line[x * 3 + 2] = mix[2];
    674  - }
    675  - else
    676  - {
    677  - line[x * 3] = 0;
    678  - line[x * 3 + 1] = 0;
    679  - line[x * 3 + 2] = 0;
    680  - }
    681  - )
    682  - }
    683  - else
    684  - {
    685  - REPEAT
    686  - (
    687  - MASK_UPDATE();
    688  - if (mask & mixmask)
    689  - {
    690  - line[x * 3] =
    691  - prevline[x * 3] ^ mix [0];
    692  - line[x * 3 + 1] =
    693  - prevline[x * 3 + 1] ^ mix [1];
    694  - line[x * 3 + 2] =
    695  - prevline[x * 3 + 2] ^ mix [2];
    696  - }
    697  - else
    698  - {
    699  - line[x * 3] =
    700  - prevline[x * 3];
    701  - line[x * 3 + 1] =
    702  - prevline[x * 3 + 1];
    703  - line[x * 3 + 2] =
    704  - prevline[x * 3 + 2];
    705  - }
    706  - )
    707  - }
    708  - break;
    709  - case 3: /* Colour */
    710  - REPEAT
    711  - (
    712  - line[x * 3] = colour2 [0];
    713  - line[x * 3 + 1] = colour2 [1];
    714  - line[x * 3 + 2] = colour2 [2];
    715  - )
    716  - break;
    717  - case 4: /* Copy */
    718  - REPEAT
    719  - (
    720  - line[x * 3] = CVAL(input);
    721  - line[x * 3 + 1] = CVAL(input);
    722  - line[x * 3 + 2] = CVAL(input);
    723  - )
    724  - break;
    725  - case 8: /* Bicolour */
    726  - REPEAT
    727  - (
    728  - if (bicolour)
    729  - {
    730  - line[x * 3] = colour2[0];
    731  - line[x * 3 + 1] = colour2[1];
    732  - line[x * 3 + 2] = colour2[2];
    733  - bicolour = False;
    734  - }
    735  - else
    736  - {
    737  - line[x * 3] = colour1[0];
    738  - line[x * 3 + 1] = colour1[1];
    739  - line[x * 3 + 2] = colour1[2];
    740  - bicolour = True;
    741  - count++;
    742  - }
    743  - )
    744  - break;
    745  - case 0xd: /* White */
    746  - REPEAT
    747  - (
    748  - line[x * 3] = 0xff;
    749  - line[x * 3 + 1] = 0xff;
    750  - line[x * 3 + 2] = 0xff;
    751  - )
    752  - break;
    753  - case 0xe: /* Black */
    754  - REPEAT
    755  - (
    756  - line[x * 3] = 0;
    757  - line[x * 3 + 1] = 0;
    758  - line[x * 3 + 2] = 0;
    759  - )
    760  - break;
    761  - default:
    762  - unimpl("bitmap opcode 0x%x\n", opcode);
    763  - return False;
    764  - }
    765  - }
    766  - }
    767  - return True;
    768  -}
    769  - 
    770  -/* decompress a colour plane */
    771  -static int
    772  -process_plane(uint8 * in, int width, int height, uint8 * out, int size)
    773  -{
    774  - int indexw;
    775  - int indexh;
    776  - int code;
    777  - int collen;
    778  - int replen;
    779  - int color;
    780  - int x;
    781  - int revcode;
    782  - uint8 * last_line;
    783  - uint8 * this_line;
    784  - uint8 * org_in;
    785  - uint8 * org_out;
    786  - 
    787  - org_in = in;
    788  - org_out = out;
    789  - last_line = 0;
    790  - indexh = 0;
    791  - while (indexh < height)
    792  - {
    793  - out = (org_out + width * height * 4) - ((indexh + 1) * width * 4);
    794  - color = 0;
    795  - this_line = out;
    796  - indexw = 0;
    797  - if (last_line == 0)
    798  - {
    799  - while (indexw < width)
    800  - {
    801  - code = CVAL(in);
    802  - replen = code & 0xf;
    803  - collen = (code >> 4) & 0xf;
    804  - revcode = (replen << 4) | collen;
    805  - if ((revcode <= 47) && (revcode >= 16))
    806  - {
    807  - replen = revcode;
    808  - collen = 0;
    809  - }
    810  - while (collen > 0)
    811  - {
    812  - color = CVAL(in);
    813  - *out = color;
    814  - out += 4;
    815  - indexw++;
    816  - collen--;
    817  - }
    818  - while (replen > 0)
    819  - {
    820  - *out = color;
    821  - out += 4;
    822  - indexw++;
    823  - replen--;
    824  - }
    825  - }
    826  - }
    827  - else
    828  - {
    829  - while (indexw < width)
    830  - {
    831  - code = CVAL(in);
    832  - replen = code & 0xf;
    833  - collen = (code >> 4) & 0xf;
    834  - revcode = (replen << 4) | collen;
    835  - if ((revcode <= 47) && (revcode >= 16))
    836  - {
    837  - replen = revcode;
    838  - collen = 0;
    839  - }
    840  - while (collen > 0)
    841  - {
    842  - x = CVAL(in);
    843  - if (x & 1)
    844  - {
    845  - x = x >> 1;
    846  - x = x + 1;
    847  - color = -x;
    848  - }
    849  - else
    850  - {
    851  - x = x >> 1;
    852  - color = x;
    853  - }
    854  - x = last_line[indexw * 4] + color;
    855  - *out = x;
    856  - out += 4;
    857  - indexw++;
    858  - collen--;
    859  - }
    860  - while (replen > 0)
    861  - {
    862  - x = last_line[indexw * 4] + color;
    863  - *out = x;
    864  - out += 4;
    865  - indexw++;
    866  - replen--;
    867  - }
    868  - }
    869  - }
    870  - indexh++;
    871  - last_line = this_line;
    872  - }
    873  - return (int) (in - org_in);
    874  -}
    875  - 
    876  -/* 4 byte bitmap decompress */
    877  -static RD_BOOL
    878  -bitmap_decompress4(uint8 * output, int width, int height, uint8 * input, int size)
    879  -{
    880  - int code;
    881  - int bytes_pro;
    882  - int total_pro;
    883  - 
    884  - code = CVAL(input);
    885  - if (code != 0x10)
    886  - {
    887  - return False;
    888  - }
    889  - total_pro = 1;
    890  - bytes_pro = process_plane(input, width, height, output + 3, size - total_pro);
    891  - total_pro += bytes_pro;
    892  - input += bytes_pro;
    893  - bytes_pro = process_plane(input, width, height, output + 2, size - total_pro);
    894  - total_pro += bytes_pro;
    895  - input += bytes_pro;
    896  - bytes_pro = process_plane(input, width, height, output + 1, size - total_pro);
    897  - total_pro += bytes_pro;
    898  - input += bytes_pro;
    899  - bytes_pro = process_plane(input, width, height, output + 0, size - total_pro);
    900  - total_pro += bytes_pro;
    901  - return size == total_pro;
    902  -}
    903  - 
    904  -/* main decompress function */
    905  -static int
    906  -bitmap_decompress(uint8 * output, int width, int height, uint8* input, int size, int Bpp)
    907  -{
    908  - RD_BOOL rv = False;
    909  - 
    910  - switch (Bpp)
    911  - {
    912  - case 1:
    913  - rv = bitmap_decompress1(output, width, height, input, size);
    914  - break;
    915  - case 2:
    916  - rv = bitmap_decompress2(output, width, height, input, size);
    917  - break;
    918  - case 3:
    919  - rv = bitmap_decompress3(output, width, height, input, size);
    920  - break;
    921  - case 4:
    922  - rv = bitmap_decompress4(output, width, height, input, size);
    923  - break;
    924  - default:
    925  - unimpl("Bpp %d\n", Bpp);
    926  - break;
    927  - }
    928  - return rv;
    929  -}
    930  - 
    931  -static void
    932  -convert_rgb555_rgb32(uint8 *decomp_buff, int decomp_buff_size, uint8 *dst, int dst_size){
    933  - int j = 0;
    934  - for(int i =0; i< decomp_buff_size; i=i+2){
    935  - int t = (decomp_buff[i+1] << 8) + decomp_buff[i];
    936  - dst[j] = t >> 8;
    937  - dst[j+1] = ((t >> 5) & 0b11111) << 3;
    938  - dst[j+2] = (t & 0x1F) << 3;
    939  - dst[j+3] = 0xff;
    940  - j = j+4;
    941  - }
    942  -}
    943  - 
    944  -static void
    945  -convert_rgb565_rgb32(uint8 *decomp_buff, int decomp_buff_size, uint8 *dst, int dst_size){
    946  - int j = 0;
    947  - for(int i =0; i< decomp_buff_size; i=i+2){
    948  - int t = (decomp_buff[i+1] << 8) + decomp_buff[i];
    949  - dst[j] = t >> 8;
    950  - dst[j+1] = ((t >> 5) & 0b111111) << 2;
    951  - dst[j+2] = (t & 0x1F) << 3;
    952  - dst[j+3] = 0xff;
    953  - j = j+4;
    954  - }
    955  -}
    956  - 
    957  -static void
    958  -convert_rgb24_rgb32(uint8 *decomp_buff, int decomp_buff_size, uint8 *dst, int dst_size){
    959  - int j = 0;
    960  - for(int i =0; i< decomp_buff_size; i=i+3){
    961  - dst[j] = decomp_buff[i];
    962  - dst[j+1] = decomp_buff[i+1];
    963  - dst[j+2] = decomp_buff[i+2];
    964  - dst[j+3] = 0xff;
    965  - j = j+4;
    966  - }
    967  -}
    968  - 
    969  -static void
    970  -convert_rgbx_rgba(uint8 *decomp_buff, int decomp_buff_size, uint8 *dst, int dst_size){
    971  - for(int i =0; i< decomp_buff_size; i=i+4){
    972  - dst[i] = decomp_buff[i];
    973  - dst[i+1] = decomp_buff[i+1];
    974  - dst[i+2] = decomp_buff[i+2];
    975  - dst[i+3] = 0xff;
    976  - }
    977  -}
    978  - 
    979  -static int
    980  -decode_rre(uint8 *rre_buff, int rre_buff_size, uint8 *dst, int dst_size, uint bypp, uint width, uint height){
    981  - uint sub_rect_num = (rre_buff[0] << 24) + (rre_buff[1] << 16) + (rre_buff[2] << 8) + rre_buff[3];
    982  - uint sub_rect_num_bytes = sub_rect_num*12;
    983  - uint rectangle_pixel_count = width*height;
    984  - uint rectangle_size = rectangle_pixel_count*bypp;
    985  - uint subrectangle_pixel_count, subrect_color_offset, subwidth_bytes = 0;
    986  - uint16 subx, suby, subwidth, subheight, substart = 0;
    987  - 
    988  - if(rectangle_size > dst_size){
    989  - return 1;
    990  - }
    991  - 
    992  - // filling rectangle with default pattern
    993  - for(uint i = 0; i< rectangle_size; i += bypp){
    994  - dst[i] = rre_buff[4];
    995  - dst[i+1] = rre_buff[5];
    996  - dst[i+2] = rre_buff[6];
    997  - dst[i+3] = 0xff; // alpha channel
    998  - }
    999  -
    1000  - if((((sub_rect_num*12)+8)) != (uint)rre_buff_size){
    1001  - printf("sub_rect_num %d\r\n", sub_rect_num);
    1002  - printf("boundary %d\r\n", ((sub_rect_num*12)+8));
    1003  - printf("rre_buff_size %d\r\n", rre_buff_size);
    1004  - return 1;
    1005  - }
    1006  - 
    1007  - for(uint i =0; i < sub_rect_num_bytes; i+=12){
    1008  - //memo: 12 = 4(RGBX) + subx, suby, subwidth, subheight
    1009  - subx = (rre_buff[8+4+i] << 8) + rre_buff[8+5+i];
    1010  - suby = (rre_buff[8+6+i] << 8) + rre_buff[8+7+i];
    1011  - subwidth = (rre_buff[8+8+i] << 8) + rre_buff[8+9+i];
    1012  - subwidth_bytes = subwidth*4;
    1013  - subheight = (rre_buff[8+10+i] << 8) + rre_buff[8+11+i];
    1014  - subrectangle_pixel_count = subwidth*subheight;
    1015  - subrect_color_offset = 8+i; // 8 is the start of subrects
    1016  - 
    1017  - for(uint j = 0; j< subrectangle_pixel_count; j += 1){
    1018  - for(uint y = 0; y < subheight; y += 1){
    1019  - substart = (subx + ((suby+y)*width))*bypp;
    1020  - if(substart > (uint)dst_size || substart + subwidth_bytes > (uint)dst_size){
    1021  - return 1;
    1022  - }
    1023  - for(uint x = 0; x < subwidth_bytes; x += 4){
    1024  - dst[substart+x] = rre_buff[subrect_color_offset];
    1025  - dst[substart+x+1] = rre_buff[subrect_color_offset+1];
    1026  - dst[substart+x+2] = rre_buff[subrect_color_offset+2];
    1027  - dst[substart+x+3] = 0xff; // alpha channel
    1028  - }
    1029  - }
    1030  - }
    1031  - }
    1032  - return 0;
    1033  - 
    1034  -}
    1035  - 
    1036  -/* *INDENT-ON* */
    1037  - 
    1038  -static PyObject*
    1039  -bitmap_decompress_wrapper(PyObject* self, PyObject* args)
    1040  -{
    1041  - Py_buffer output, input;
    1042  - int width = 0, height = 0, bpp = 0, bitsperpixel = 0, isCompressed = 0;
    1043  - int decomp_size = 0;
    1044  - uint8 *decomp_buffer = NULL;
    1045  - 
    1046  - if (!PyArg_ParseTuple(args, "s*iis*iii", &output, &width, &height, &input, &bitsperpixel, &bpp, &isCompressed)){
    1047  - PyErr_SetString(PyExc_TypeError, "Input parameter error");
    1048  - return (PyObject *) NULL;
    1049  - }
    1050  -
    1051  - if(isCompressed){
    1052  - decomp_size = width * height * bpp;
    1053  - decomp_buffer = (uint8*)malloc(decomp_size);
    1054  - 
    1055  - if(decomp_buffer == NULL){
    1056  - PyErr_SetString(PyExc_TypeError, "malloc failed!");
    1057  - return (PyObject *) NULL;
    1058  - }
    1059  - 
    1060  - if(bitmap_decompress(decomp_buffer, width, height, (uint8*)input.buf, input.len, bpp) == False){
    1061  - free(decomp_buffer);
    1062  - PyErr_SetString(PyExc_TypeError, "Decompression error");
    1063  - return (PyObject *) NULL;
    1064  - }
    1065  - }
    1066  - else{
    1067  - decomp_buffer = (uint8*)input.buf;
    1068  - decomp_size = input.len;
    1069  - }
    1070  -
    1071  - 
    1072  - switch(bitsperpixel){
    1073  - case 15:
    1074  - convert_rgb555_rgb32(decomp_buffer, decomp_size, (uint8*)output.buf, output.len);
    1075  - break;
    1076  - case 16:
    1077  - convert_rgb565_rgb32(decomp_buffer, decomp_size, (uint8*)output.buf, output.len);
    1078  - break;
    1079  - case 24:
    1080  - convert_rgb24_rgb32(decomp_buffer, decomp_size, (uint8*)output.buf, output.len);
    1081  - break;
    1082  - case 32:
    1083  - break;
    1084  - }
    1085  - if(isCompressed){
    1086  - free(decomp_buffer);
    1087  - }
    1088  - 
    1089  - Py_RETURN_NONE;
    1090  -}
    1091  - 
    1092  -static PyObject*
    1093  -mask_rgbx_wrapper(PyObject* self, PyObject* args)
    1094  -{
    1095  - Py_buffer output, input;
    1096  - 
    1097  - if (!PyArg_ParseTuple(args, "s*s*", &output, &input)){
    1098  - PyErr_SetString(PyExc_TypeError, "Input parameter error");
    1099  - return (PyObject *) NULL;
    1100  - }
    1101  - 
    1102  - convert_rgbx_rgba((uint8*)input.buf, input.len, (uint8*)output.buf, output.len);
    1103  -
    1104  - 
    1105  - Py_RETURN_NONE;
    1106  -}
    1107  - 
    1108  -static PyObject*
    1109  -decode_rre_wrapper(PyObject* self, PyObject* args)
    1110  -{
    1111  - Py_buffer output, input;
    1112  - int width = 0, height = 0, bypp = 0;
    1113  - 
    1114  - if (!PyArg_ParseTuple(args, "s*s*iii", &output, &input, &width, &height, &bypp)){
    1115  - PyErr_SetString(PyExc_TypeError, "Input parameter error");
    1116  - return (PyObject *) NULL;
    1117  - }
    1118  -
    1119  - if(decode_rre((uint8*)input.buf, input.len, (uint8*)output.buf, output.len, bypp, width, height)){
    1120  - PyErr_SetString(PyExc_TypeError, "Decode failed!");
    1121  - return (PyObject *) NULL;
    1122  - }
    1123  -
    1124  - Py_RETURN_NONE;
    1125  -}
    1126  - 
    1127  -static PyMethodDef rle_methods[] =
    1128  -{
    1129  - {"bitmap_decompress", bitmap_decompress_wrapper, METH_VARARGS, "decompress bitmap from microsoft rle algorithm."},
    1130  - {"mask_rgbx", mask_rgbx_wrapper, METH_VARARGS, "Converts RGBX to RGBA"},
    1131  - {"decode_rre", decode_rre_wrapper, METH_VARARGS, "Converts RRE encoded data to RGBA recatngle"},
    1132  - {NULL, NULL, 0, NULL}
    1133  -};
    1134  - 
    1135  -static struct PyModuleDef cModPyDem =
    1136  -{
    1137  - PyModuleDef_HEAD_INIT,
    1138  - "rle", /* name of module */
    1139  - "", /* module documentation, may be NULL */
    1140  - -1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
    1141  - rle_methods
    1142  -};
    1143  - 
    1144  -static volatile int *_dummy_malloc;
    1145  - 
    1146  -PyMODINIT_FUNC PyInit_rle(void)
    1147  -{
    1148  - // This is for pyodide for some reason it didn't work without it.
    1149  - _dummy_malloc = (int *)malloc(sizeof(int));
    1150  - *_dummy_malloc = 1;
    1151  - free((void *)_dummy_malloc);
    1152  - // yup.
    1153  - 
    1154  - PyObject *m = PyModule_Create(&cModPyDem);
    1155  - return m;
    1156  -};
    1157  - 
    1158  - 
  • ■ ■ ■ ■ ■ ■
    aardwolf/utils/rle/rle_working.c
    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 seperate function for speed when decompressing the bitmaps
    21  - when modifing one function make the change in the others
    22  - [email protected] */
    23  - 
    24  -/* indent is confused by this file */
    25  -/* *INDENT-OFF* */
    26  - 
    27  -#include <stdlib.h>
    28  -#include <Python.h>
    29  - 
    30  -/* Specific rename for RDPY integration */
    31  -#define uint8 unsigned char
    32  -#define uint16 unsigned short
    33  -#define unimpl(str, code)
    34  - 
    35  -#define RD_BOOL int
    36  -#define False 0
    37  -#define True 1
    38  -/* end specific rename */
    39  - 
    40  -#define CVAL(p) (*(p++))
    41  -#ifdef NEED_ALIGN
    42  -#ifdef L_ENDIAN
    43  -#define CVAL2(p, v) { v = (*(p++)); v |= (*(p++)) << 8; }
    44  -#else
    45  -#define CVAL2(p, v) { v = (*(p++)) << 8; v |= (*(p++)); }
    46  -#endif /* L_ENDIAN */
    47  -#else
    48  -#define CVAL2(p, v) { v = (*((uint16*)p)); p += 2; }
    49  -#endif /* NEED_ALIGN */
    50  - 
    51  -#define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
    52  - 
    53  -#define REPEAT(statement) \
    54  -{ \
    55  - while((count & ~0x7) && ((x+8) < width)) \
    56  - UNROLL8( statement; count--; x++; ); \
    57  - \
    58  - while((count > 0) && (x < width)) \
    59  - { \
    60  - statement; \
    61  - count--; \
    62  - x++; \
    63  - } \
    64  -}
    65  - 
    66  -#define MASK_UPDATE() \
    67  -{ \
    68  - mixmask <<= 1; \
    69  - if (mixmask == 0) \
    70  - { \
    71  - mask = fom_mask ? fom_mask : CVAL(input); \
    72  - mixmask = 1; \
    73  - } \
    74  -}
    75  - 
    76  -/* 1 byte bitmap decompress */
    77  -static RD_BOOL
    78  -bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size)
    79  -{
    80  - uint8 *end = input + size;
    81  - uint8 *prevline = NULL, *line = NULL;
    82  - int opcode, count, offset, isfillormix, x = width;
    83  - int lastopcode = -1, insertmix = False, bicolour = False;
    84  - uint8 code;
    85  - uint8 colour1 = 0, colour2 = 0;
    86  - uint8 mixmask, mask = 0;
    87  - uint8 mix = 0xff;
    88  - int fom_mask = 0;
    89  - 
    90  - while (input < end)
    91  - {
    92  - fom_mask = 0;
    93  - code = CVAL(input);
    94  - opcode = code >> 4;
    95  - /* Handle different opcode forms */
    96  - switch (opcode)
    97  - {
    98  - case 0xc:
    99  - case 0xd:
    100  - case 0xe:
    101  - opcode -= 6;
    102  - count = code & 0xf;
    103  - offset = 16;
    104  - break;
    105  - case 0xf:
    106  - opcode = code & 0xf;
    107  - if (opcode < 9)
    108  - {
    109  - count = CVAL(input);
    110  - count |= CVAL(input) << 8;
    111  - }
    112  - else
    113  - {
    114  - count = (opcode < 0xb) ? 8 : 1;
    115  - }
    116  - offset = 0;
    117  - break;
    118  - default:
    119  - opcode >>= 1;
    120  - count = code & 0x1f;
    121  - offset = 32;
    122  - break;
    123  - }
    124  - /* Handle strange cases for counts */
    125  - if (offset != 0)
    126  - {
    127  - isfillormix = ((opcode == 2) || (opcode == 7));
    128  - if (count == 0)
    129  - {
    130  - if (isfillormix)
    131  - count = CVAL(input) + 1;
    132  - else
    133  - count = CVAL(input) + offset;
    134  - }
    135  - else if (isfillormix)
    136  - {
    137  - count <<= 3;
    138  - }
    139  - }
    140  - /* Read preliminary data */
    141  - switch (opcode)
    142  - {
    143  - case 0: /* Fill */
    144  - if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
    145  - insertmix = True;
    146  - break;
    147  - case 8: /* Bicolour */
    148  - colour1 = CVAL(input);
    149  - case 3: /* Colour */
    150  - colour2 = CVAL(input);
    151  - break;
    152  - case 6: /* SetMix/Mix */
    153  - case 7: /* SetMix/FillOrMix */
    154  - mix = CVAL(input);
    155  - opcode -= 5;
    156  - break;
    157  - case 9: /* FillOrMix_1 */
    158  - mask = 0x03;
    159  - opcode = 0x02;
    160  - fom_mask = 3;
    161  - break;
    162  - case 0x0a: /* FillOrMix_2 */
    163  - mask = 0x05;
    164  - opcode = 0x02;
    165  - fom_mask = 5;
    166  - break;
    167  - }
    168  - lastopcode = opcode;
    169  - mixmask = 0;
    170  - /* Output body */
    171  - while (count > 0)
    172  - {
    173  - if (x >= width)
    174  - {
    175  - if (height <= 0)
    176  - return False;
    177  - x = 0;
    178  - height--;
    179  - prevline = line;
    180  - line = output + height * width;
    181  - }
    182  - switch (opcode)
    183  - {
    184  - case 0: /* Fill */
    185  - if (insertmix)
    186  - {
    187  - if (prevline == NULL)
    188  - line[x] = mix;
    189  - else
    190  - line[x] = prevline[x] ^ mix;
    191  - insertmix = False;
    192  - count--;
    193  - x++;
    194  - }
    195  - if (prevline == NULL)
    196  - {
    197  - REPEAT(line[x] = 0)
    198  - }
    199  - else
    200  - {
    201  - REPEAT(line[x] = prevline[x])
    202  - }
    203  - break;
    204  - case 1: /* Mix */
    205  - if (prevline == NULL)
    206  - {
    207  - REPEAT(line[x] = mix)
    208  - }
    209  - else
    210  - {
    211  - REPEAT(line[x] = prevline[x] ^ mix)
    212  - }
    213  - break;
    214  - case 2: /* Fill or Mix */
    215  - if (prevline == NULL)
    216  - {
    217  - REPEAT
    218  - (
    219  - MASK_UPDATE();
    220  - if (mask & mixmask)
    221  - line[x] = mix;
    222  - else
    223  - line[x] = 0;
    224  - )
    225  - }
    226  - else
    227  - {
    228  - REPEAT
    229  - (
    230  - MASK_UPDATE();
    231  - if (mask & mixmask)
    232  - line[x] = prevline[x] ^ mix;
    233  - else
    234  - line[x] = prevline[x];
    235  - )
    236  - }
    237  - break;
    238  - case 3: /* Colour */
    239  - REPEAT(line[x] = colour2)
    240  - break;
    241  - case 4: /* Copy */
    242  - REPEAT(line[x] = CVAL(input))
    243  - break;
    244  - case 8: /* Bicolour */
    245  - REPEAT
    246  - (
    247  - if (bicolour)
    248  - {
    249  - line[x] = colour2;
    250  - bicolour = False;
    251  - }
    252  - else
    253  - {
    254  - line[x] = colour1;
    255  - bicolour = True; count++;
    256  - }
    257  - )
    258  - break;
    259  - case 0xd: /* White */
    260  - REPEAT(line[x] = 0xff)
    261  - break;
    262  - case 0xe: /* Black */
    263  - REPEAT(line[x] = 0)
    264  - break;
    265  - default:
    266  - unimpl("bitmap opcode 0x%x\n", opcode);
    267  - return False;
    268  - }
    269  - }
    270  - }
    271  - return True;
    272  -}
    273  - 
    274  -/* 2 byte bitmap decompress */
    275  -static RD_BOOL
    276  -bitmap_decompress2(uint8 * output, int width, int height, uint8 * input, int size)
    277  -{
    278  - uint8 *end = input + size;
    279  - uint16 *prevline = NULL, *line = NULL;
    280  - int opcode, count, offset, isfillormix, x = width;
    281  - int lastopcode = -1, insertmix = False, bicolour = False;
    282  - uint8 code;
    283  - uint16 colour1 = 0, colour2 = 0;
    284  - uint8 mixmask, mask = 0;
    285  - uint16 mix = 0xffff;
    286  - int fom_mask = 0;
    287  - 
    288  - while (input < end)
    289  - {
    290  - fom_mask = 0;
    291  - code = CVAL(input);
    292  - opcode = code >> 4;
    293  - /* Handle different opcode forms */
    294  - switch (opcode)
    295  - {
    296  - case 0xc:
    297  - case 0xd:
    298  - case 0xe:
    299  - opcode -= 6;
    300  - count = code & 0xf;
    301  - offset = 16;
    302  - break;
    303  - case 0xf:
    304  - opcode = code & 0xf;
    305  - if (opcode < 9)
    306  - {
    307  - count = CVAL(input);
    308  - count |= CVAL(input) << 8;
    309  - }
    310  - else
    311  - {
    312  - count = (opcode < 0xb) ? 8 : 1;
    313  - }
    314  - offset = 0;
    315  - break;
    316  - default:
    317  - opcode >>= 1;
    318  - count = code & 0x1f;
    319  - offset = 32;
    320  - break;
    321  - }
    322  - /* Handle strange cases for counts */
    323  - if (offset != 0)
    324  - {
    325  - isfillormix = ((opcode == 2) || (opcode == 7));
    326  - if (count == 0)
    327  - {
    328  - if (isfillormix)
    329  - count = CVAL(input) + 1;
    330  - else
    331  - count = CVAL(input) + offset;
    332  - }
    333  - else if (isfillormix)
    334  - {
    335  - count <<= 3;
    336  - }
    337  - }
    338  - /* Read preliminary data */
    339  - switch (opcode)
    340  - {
    341  - case 0: /* Fill */
    342  - if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
    343  - insertmix = True;
    344  - break;
    345  - case 8: /* Bicolour */
    346  - CVAL2(input, colour1);
    347  - case 3: /* Colour */
    348  - CVAL2(input, colour2);
    349  - break;
    350  - case 6: /* SetMix/Mix */
    351  - case 7: /* SetMix/FillOrMix */
    352  - CVAL2(input, mix);
    353  - opcode -= 5;
    354  - break;
    355  - case 9: /* FillOrMix_1 */
    356  - mask = 0x03;
    357  - opcode = 0x02;
    358  - fom_mask = 3;
    359  - break;
    360  - case 0x0a: /* FillOrMix_2 */
    361  - mask = 0x05;
    362  - opcode = 0x02;
    363  - fom_mask = 5;
    364  - break;
    365  - }
    366  - lastopcode = opcode;
    367  - mixmask = 0;
    368  - /* Output body */
    369  - while (count > 0)
    370  - {
    371  - if (x >= width)
    372  - {
    373  - if (height <= 0)
    374  - return False;
    375  - x = 0;
    376  - height--;
    377  - prevline = line;
    378  - line = ((uint16 *) output) + height * width;
    379  - }
    380  - switch (opcode)
    381  - {
    382  - case 0: /* Fill */
    383  - if (insertmix)
    384  - {
    385  - if (prevline == NULL)
    386  - line[x] = mix;
    387  - else
    388  - line[x] = prevline[x] ^ mix;
    389  - insertmix = False;
    390  - count--;
    391  - x++;
    392  - }
    393  - if (prevline == NULL)
    394  - {
    395  - REPEAT(line[x] = 0)
    396  - }
    397  - else
    398  - {
    399  - REPEAT(line[x] = prevline[x])
    400  - }
    401  - break;
    402  - case 1: /* Mix */
    403  - if (prevline == NULL)
    404  - {
    405  - REPEAT(line[x] = mix)
    406  - }
    407  - else
    408  - {
    409  - REPEAT(line[x] = prevline[x] ^ mix)
    410  - }
    411  - break;
    412  - case 2: /* Fill or Mix */
    413  - if (prevline == NULL)
    414  - {
    415  - REPEAT
    416  - (
    417  - MASK_UPDATE();
    418  - if (mask & mixmask)
    419  - line[x] = mix;
    420  - else
    421  - line[x] = 0;
    422  - )
    423  - }
    424  - else
    425  - {
    426  - REPEAT
    427  - (
    428  - MASK_UPDATE();
    429  - if (mask & mixmask)
    430  - line[x] = prevline[x] ^ mix;
    431  - else
    432  - line[x] = prevline[x];
    433  - )
    434  - }
    435  - break;
    436  - case 3: /* Colour */
    437  - REPEAT(line[x] = colour2)
    438  - break;
    439  - case 4: /* Copy */
    440  - REPEAT(CVAL2(input, line[x]))
    441  - break;
    442  - case 8: /* Bicolour */
    443  - REPEAT
    444  - (
    445  - if (bicolour)
    446  - {
    447  - line[x] = colour2;
    448  - bicolour = False;
    449  - }
    450  - else
    451  - {
    452  - line[x] = colour1;
    453  - bicolour = True;
    454  - count++;
    455  - }
    456  - )
    457  - break;
    458  - case 0xd: /* White */
    459  - REPEAT(line[x] = 0xffff)
    460  - break;
    461  - case 0xe: /* Black */
    462  - REPEAT(line[x] = 0)
    463  - break;
    464  - default:
    465  - unimpl("bitmap opcode 0x%x\n", opcode);
    466  - return False;
    467  - }
    468  - }
    469  - }
    470  - return True;
    471  -}
    472  - 
    473  -/* 3 byte bitmap decompress */
    474  -static RD_BOOL
    475  -bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int size)
    476  -{
    477  - uint8 *end = input + size;
    478  - uint8 *prevline = NULL, *line = NULL;
    479  - int opcode, count, offset, isfillormix, x = width;
    480  - int lastopcode = -1, insertmix = False, bicolour = False;
    481  - uint8 code;
    482  - uint8 colour1[3] = {0, 0, 0}, colour2[3] = {0, 0, 0};
    483  - uint8 mixmask, mask = 0;
    484  - uint8 mix[3] = {0xff, 0xff, 0xff};
    485  - int fom_mask = 0;
    486  - 
    487  - while (input < end)
    488  - {
    489  - fom_mask = 0;
    490  - code = CVAL(input);
    491  - opcode = code >> 4;
    492  - /* Handle different opcode forms */
    493  - switch (opcode)
    494  - {
    495  - case 0xc:
    496  - case 0xd:
    497  - case 0xe:
    498  - opcode -= 6;
    499  - count = code & 0xf;
    500  - offset = 16;
    501  - break;
    502  - case 0xf:
    503  - opcode = code & 0xf;
    504  - if (opcode < 9)
    505  - {
    506  - count = CVAL(input);
    507  - count |= CVAL(input) << 8;
    508  - }
    509  - else
    510  - {
    511  - count = (opcode <
    512  - 0xb) ? 8 : 1;
    513  - }
    514  - offset = 0;
    515  - break;
    516  - default:
    517  - opcode >>= 1;
    518  - count = code & 0x1f;
    519  - offset = 32;
    520  - break;
    521  - }
    522  - /* Handle strange cases for counts */
    523  - if (offset != 0)
    524  - {
    525  - isfillormix = ((opcode == 2) || (opcode == 7));
    526  - if (count == 0)
    527  - {
    528  - if (isfillormix)
    529  - count = CVAL(input) + 1;
    530  - else
    531  - count = CVAL(input) + offset;
    532  - }
    533  - else if (isfillormix)
    534  - {
    535  - count <<= 3;
    536  - }
    537  - }
    538  - /* Read preliminary data */
    539  - switch (opcode)
    540  - {
    541  - case 0: /* Fill */
    542  - if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
    543  - insertmix = True;
    544  - break;
    545  - case 8: /* Bicolour */
    546  - colour1[0] = CVAL(input);
    547  - colour1[1] = CVAL(input);
    548  - colour1[2] = CVAL(input);
    549  - case 3: /* Colour */
    550  - colour2[0] = CVAL(input);
    551  - colour2[1] = CVAL(input);
    552  - colour2[2] = CVAL(input);
    553  - break;
    554  - case 6: /* SetMix/Mix */
    555  - case 7: /* SetMix/FillOrMix */
    556  - mix[0] = CVAL(input);
    557  - mix[1] = CVAL(input);
    558  - mix[2] = CVAL(input);
    559  - opcode -= 5;
    560  - break;
    561  - case 9: /* FillOrMix_1 */
    562  - mask = 0x03;
    563  - opcode = 0x02;
    564  - fom_mask = 3;
    565  - break;
    566  - case 0x0a: /* FillOrMix_2 */
    567  - mask = 0x05;
    568  - opcode = 0x02;
    569  - fom_mask = 5;
    570  - break;
    571  - }
    572  - lastopcode = opcode;
    573  - mixmask = 0;
    574  - /* Output body */
    575  - while (count > 0)
    576  - {
    577  - if (x >= width)
    578  - {
    579  - if (height <= 0)
    580  - return False;
    581  - x = 0;
    582  - height--;
    583  - prevline = line;
    584  - line = output + height * (width * 3);
    585  - }
    586  - switch (opcode)
    587  - {
    588  - case 0: /* Fill */
    589  - if (insertmix)
    590  - {
    591  - if (prevline == NULL)
    592  - {
    593  - line[x * 3] = mix[0];
    594  - line[x * 3 + 1] = mix[1];
    595  - line[x * 3 + 2] = mix[2];
    596  - }
    597  - else
    598  - {
    599  - line[x * 3] =
    600  - prevline[x * 3] ^ mix[0];
    601  - line[x * 3 + 1] =
    602  - prevline[x * 3 + 1] ^ mix[1];
    603  - line[x * 3 + 2] =
    604  - prevline[x * 3 + 2] ^ mix[2];
    605  - }
    606  - insertmix = False;
    607  - count--;
    608  - x++;
    609  - }
    610  - if (prevline == NULL)
    611  - {
    612  - REPEAT
    613  - (
    614  - line[x * 3] = 0;
    615  - line[x * 3 + 1] = 0;
    616  - line[x * 3 + 2] = 0;
    617  - )
    618  - }
    619  - else
    620  - {
    621  - REPEAT
    622  - (
    623  - line[x * 3] = prevline[x * 3];
    624  - line[x * 3 + 1] = prevline[x * 3 + 1];
    625  - line[x * 3 + 2] = prevline[x * 3 + 2];
    626  - )
    627  - }
    628  - break;
    629  - case 1: /* Mix */
    630  - if (prevline == NULL)
    631  - {
    632  - REPEAT
    633  - (
    634  - line[x * 3] = mix[0];
    635  - line[x * 3 + 1] = mix[1];
    636  - line[x * 3 + 2] = mix[2];
    637  - )
    638  - }
    639  - else
    640  - {
    641  - REPEAT
    642  - (
    643  - line[x * 3] =
    644  - prevline[x * 3] ^ mix[0];
    645  - line[x * 3 + 1] =
    646  - prevline[x * 3 + 1] ^ mix[1];
    647  - line[x * 3 + 2] =
    648  - prevline[x * 3 + 2] ^ mix[2];
    649  - )
    650  - }
    651  - break;
    652  - case 2: /* Fill or Mix */
    653  - if (prevline == NULL)
    654  - {
    655  - REPEAT
    656  - (
    657  - MASK_UPDATE();
    658  - if (mask & mixmask)
    659  - {
    660  - line[x * 3] = mix[0];
    661  - line[x * 3 + 1] = mix[1];
    662  - line[x * 3 + 2] = mix[2];
    663  - }
    664  - else
    665  - {
    666  - line[x * 3] = 0;
    667  - line[x * 3 + 1] = 0;
    668  - line[x * 3 + 2] = 0;
    669  - }
    670  - )
    671  - }
    672  - else
    673  - {
    674  - REPEAT
    675  - (
    676  - MASK_UPDATE();
    677  - if (mask & mixmask)
    678  - {
    679  - line[x * 3] =
    680  - prevline[x * 3] ^ mix [0];
    681  - line[x * 3 + 1] =
    682  - prevline[x * 3 + 1] ^ mix [1];
    683  - line[x * 3 + 2] =
    684  - prevline[x * 3 + 2] ^ mix [2];
    685  - }
    686  - else
    687  - {
    688  - line[x * 3] =
    689  - prevline[x * 3];
    690  - line[x * 3 + 1] =
    691  - prevline[x * 3 + 1];
    692  - line[x * 3 + 2] =
    693  - prevline[x * 3 + 2];
    694  - }
    695  - )
    696  - }
    697  - break;
    698  - case 3: /* Colour */
    699  - REPEAT
    700  - (
    701  - line[x * 3] = colour2 [0];
    702  - line[x * 3 + 1] = colour2 [1];
    703  - line[x * 3 + 2] = colour2 [2];
    704  - )
    705  - break;
    706  - case 4: /* Copy */
    707  - REPEAT
    708  - (
    709  - line[x * 3] = CVAL(input);
    710  - line[x * 3 + 1] = CVAL(input);
    711  - line[x * 3 + 2] = CVAL(input);
    712  - )
    713  - break;
    714  - case 8: /* Bicolour */
    715  - REPEAT
    716  - (
    717  - if (bicolour)
    718  - {
    719  - line[x * 3] = colour2[0];
    720  - line[x * 3 + 1] = colour2[1];
    721  - line[x * 3 + 2] = colour2[2];
    722  - bicolour = False;
    723  - }
    724  - else
    725  - {
    726  - line[x * 3] = colour1[0];
    727  - line[x * 3 + 1] = colour1[1];
    728  - line[x * 3 + 2] = colour1[2];
    729  - bicolour = True;
    730  - count++;
    731  - }
    732  - )
    733  - break;
    734  - case 0xd: /* White */
    735  - REPEAT
    736  - (
    737  - line[x * 3] = 0xff;
    738  - line[x * 3 + 1] = 0xff;
    739  - line[x * 3 + 2] = 0xff;
    740  - )
    741  - break;
    742  - case 0xe: /* Black */
    743  - REPEAT
    744  - (
    745  - line[x * 3] = 0;
    746  - line[x * 3 + 1] = 0;
    747  - line[x * 3 + 2] = 0;
    748  - )
    749  - break;
    750  - default:
    751  - unimpl("bitmap opcode 0x%x\n", opcode);
    752  - return False;
    753  - }
    754  - }
    755  - }
    756  - return True;
    757  -}
    758  - 
    759  -/* decompress a colour plane */
    760  -static int
    761  -process_plane(uint8 * in, int width, int height, uint8 * out, int size)
    762  -{
    763  - int indexw;
    764  - int indexh;
    765  - int code;
    766  - int collen;
    767  - int replen;
    768  - int color;
    769  - int x;
    770  - int revcode;
    771  - uint8 * last_line;
    772  - uint8 * this_line;
    773  - uint8 * org_in;
    774  - uint8 * org_out;
    775  - 
    776  - org_in = in;
    777  - org_out = out;
    778  - last_line = 0;
    779  - indexh = 0;
    780  - while (indexh < height)
    781  - {
    782  - out = (org_out + width * height * 4) - ((indexh + 1) * width * 4);
    783  - color = 0;
    784  - this_line = out;
    785  - indexw = 0;
    786  - if (last_line == 0)
    787  - {
    788  - while (indexw < width)
    789  - {
    790  - code = CVAL(in);
    791  - replen = code & 0xf;
    792  - collen = (code >> 4) & 0xf;
    793  - revcode = (replen << 4) | collen;
    794  - if ((revcode <= 47) && (revcode >= 16))
    795  - {
    796  - replen = revcode;
    797  - collen = 0;
    798  - }
    799  - while (collen > 0)
    800  - {
    801  - color = CVAL(in);
    802  - *out = color;
    803  - out += 4;
    804  - indexw++;
    805  - collen--;
    806  - }
    807  - while (replen > 0)
    808  - {
    809  - *out = color;
    810  - out += 4;
    811  - indexw++;
    812  - replen--;
    813  - }
    814  - }
    815  - }
    816  - else
    817  - {
    818  - while (indexw < width)
    819  - {
    820  - code = CVAL(in);
    821  - replen = code & 0xf;
    822  - collen = (code >> 4) & 0xf;
    823  - revcode = (replen << 4) | collen;
    824  - if ((revcode <= 47) && (revcode >= 16))
    825  - {
    826  - replen = revcode;
    827  - collen = 0;
    828  - }
    829  - while (collen > 0)
    830  - {
    831  - x = CVAL(in);
    832  - if (x & 1)
    833  - {
    834  - x = x >> 1;
    835  - x = x + 1;
    836  - color = -x;
    837  - }
    838  - else
    839  - {
    840  - x = x >> 1;
    841  - color = x;
    842  - }
    843  - x = last_line[indexw * 4] + color;
    844  - *out = x;
    845  - out += 4;
    846  - indexw++;
    847  - collen--;
    848  - }
    849  - while (replen > 0)
    850  - {
    851  - x = last_line[indexw * 4] + color;
    852  - *out = x;
    853  - out += 4;
    854  - indexw++;
    855  - replen--;
    856  - }
    857  - }
    858  - }
    859  - indexh++;
    860  - last_line = this_line;
    861  - }
    862  - return (int) (in - org_in);
    863  -}
    864  - 
    865  -/* 4 byte bitmap decompress */
    866  -static RD_BOOL
    867  -bitmap_decompress4(uint8 * output, int width, int height, uint8 * input, int size)
    868  -{
    869  - int code;
    870  - int bytes_pro;
    871  - int total_pro;
    872  - 
    873  - code = CVAL(input);
    874  - if (code != 0x10)
    875  - {
    876  - return False;
    877  - }
    878  - total_pro = 1;
    879  - bytes_pro = process_plane(input, width, height, output + 3, size - total_pro);
    880  - total_pro += bytes_pro;
    881  - input += bytes_pro;
    882  - bytes_pro = process_plane(input, width, height, output + 2, size - total_pro);
    883  - total_pro += bytes_pro;
    884  - input += bytes_pro;
    885  - bytes_pro = process_plane(input, width, height, output + 1, size - total_pro);
    886  - total_pro += bytes_pro;
    887  - input += bytes_pro;
    888  - bytes_pro = process_plane(input, width, height, output + 0, size - total_pro);
    889  - total_pro += bytes_pro;
    890  - return size == total_pro;
    891  -}
    892  - 
    893  -/* main decompress function */
    894  -static int
    895  -bitmap_decompress(uint8 * output, int width, int height, uint8* input, int size, int Bpp)
    896  -{
    897  - RD_BOOL rv = False;
    898  - 
    899  - switch (Bpp)
    900  - {
    901  - case 1:
    902  - rv = bitmap_decompress1(output, width, height, input, size);
    903  - break;
    904  - case 2:
    905  - rv = bitmap_decompress2(output, width, height, input, size);
    906  - break;
    907  - case 3:
    908  - rv = bitmap_decompress3(output, width, height, input, size);
    909  - break;
    910  - case 4:
    911  - rv = bitmap_decompress4(output, width, height, input, size);
    912  - break;
    913  - default:
    914  - unimpl("Bpp %d\n", Bpp);
    915  - break;
    916  - }
    917  - return rv;
    918  -}
    919  - 
    920  -/* *INDENT-ON* */
    921  - 
    922  -static PyObject*
    923  -bitmap_decompress_wrapper(PyObject* self, PyObject* args)
    924  -{
    925  - Py_buffer output, input;
    926  - int width = 0, height = 0, bpp = 0;
    927  - 
    928  - if (!PyArg_ParseTuple(args, "s*iis*i", &output, &width, &height, &input, &bpp)){
    929  - PyErr_SetString(PyExc_TypeError, "Input parameter error");
    930  - return (PyObject *) NULL;
    931  - }
    932  -
    933  - 
    934  - if(bitmap_decompress((uint8*)output.buf, width, height, (uint8*)input.buf, input.len, bpp) == False){
    935  - PyErr_SetString(PyExc_TypeError, "Decompression error");
    936  - return (PyObject *) NULL;
    937  - }
    938  -
    939  - 
    940  - Py_RETURN_NONE;
    941  -}
    942  - 
    943  -static PyMethodDef rle_methods[] =
    944  -{
    945  - {"bitmap_decompress", bitmap_decompress_wrapper, METH_VARARGS, "decompress bitmap from microsoft rle algorithm."},
    946  - {NULL, NULL, 0, NULL}
    947  -};
    948  - 
    949  -static struct PyModuleDef cModPyDem =
    950  -{
    951  - PyModuleDef_HEAD_INIT,
    952  - "rle", /* name of module */
    953  - "", /* module documentation, may be NULL */
    954  - -1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
    955  - rle_methods
    956  -};
    957  - 
    958  -static volatile int *_dummy_malloc;
    959  - 
    960  -PyMODINIT_FUNC PyInit_rle(void)
    961  -{
    962  -
    963  - _dummy_malloc = (int *)malloc(sizeof(int));
    964  - *_dummy_malloc = 1;
    965  - free((void *)_dummy_malloc);
    966  - 
    967  - PyObject *m = PyModule_Create(&cModPyDem);
    968  - return m;
    969  -};
    970  - 
    971  - 
  • ■ ■ ■ ■ ■ ■
    aardwolf/utils/rle/test.py
    1  -from distutils.core import setup, Extension
    2  - 
    3  -rle_module = Extension('rle',
    4  - define_macros = [('MAJOR_VERSION', '1'), ('MINOR_VERSION', '0')],
    5  - include_dirs = ['/usr/local/include'],
    6  - library_dirs = ['/usr/local/lib'],
    7  - sources = ['rle.c'])
    8  - 
    9  -setup (name = 'rle',
    10  - ext_modules = [rle_module]
    11  -)
  • ■ ■ ■ ■ ■ ■
    aardwolf/utils/rlers/Cargo.lock
     1 +# This file is automatically @generated by Cargo.
     2 +# It is not intended for manual editing.
     3 +version = 3
     4 + 
     5 +[[package]]
     6 +name = "autocfg"
     7 +version = "1.1.0"
     8 +source = "registry+https://github.com/rust-lang/crates.io-index"
     9 +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
     10 + 
     11 +[[package]]
     12 +name = "bitflags"
     13 +version = "1.3.2"
     14 +source = "registry+https://github.com/rust-lang/crates.io-index"
     15 +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
     16 + 
     17 +[[package]]
     18 +name = "byteorder"
     19 +version = "1.4.3"
     20 +source = "registry+https://github.com/rust-lang/crates.io-index"
     21 +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
     22 + 
     23 +[[package]]
     24 +name = "cfg-if"
     25 +version = "1.0.0"
     26 +source = "registry+https://github.com/rust-lang/crates.io-index"
     27 +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
     28 + 
     29 +[[package]]
     30 +name = "derivative"
     31 +version = "2.2.0"
     32 +source = "registry+https://github.com/rust-lang/crates.io-index"
     33 +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
     34 +dependencies = [
     35 + "proc-macro2",
     36 + "quote",
     37 + "syn",
     38 +]
     39 + 
     40 +[[package]]
     41 +name = "indoc"
     42 +version = "1.0.7"
     43 +source = "registry+https://github.com/rust-lang/crates.io-index"
     44 +checksum = "adab1eaa3408fb7f0c777a73e7465fd5656136fc93b670eb6df3c88c2c1344e3"
     45 + 
     46 +[[package]]
     47 +name = "lazy_static"
     48 +version = "1.4.0"
     49 +source = "registry+https://github.com/rust-lang/crates.io-index"
     50 +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
     51 + 
     52 +[[package]]
     53 +name = "libc"
     54 +version = "0.2.134"
     55 +source = "registry+https://github.com/rust-lang/crates.io-index"
     56 +checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb"
     57 + 
     58 +[[package]]
     59 +name = "lock_api"
     60 +version = "0.4.9"
     61 +source = "registry+https://github.com/rust-lang/crates.io-index"
     62 +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
     63 +dependencies = [
     64 + "autocfg",
     65 + "scopeguard",
     66 +]
     67 + 
     68 +[[package]]
     69 +name = "num_enum"
     70 +version = "0.4.3"
     71 +source = "registry+https://github.com/rust-lang/crates.io-index"
     72 +checksum = "ca565a7df06f3d4b485494f25ba05da1435950f4dc263440eda7a6fa9b8e36e4"
     73 +dependencies = [
     74 + "derivative",
     75 + "num_enum_derive",
     76 +]
     77 + 
     78 +[[package]]
     79 +name = "num_enum_derive"
     80 +version = "0.4.3"
     81 +source = "registry+https://github.com/rust-lang/crates.io-index"
     82 +checksum = "ffa5a33ddddfee04c0283a7653987d634e880347e96b5b2ed64de07efb59db9d"
     83 +dependencies = [
     84 + "proc-macro-crate",
     85 + "proc-macro2",
     86 + "quote",
     87 + "syn",
     88 +]
     89 + 
     90 +[[package]]
     91 +name = "once_cell"
     92 +version = "1.15.0"
     93 +source = "registry+https://github.com/rust-lang/crates.io-index"
     94 +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
     95 + 
     96 +[[package]]
     97 +name = "parking_lot"
     98 +version = "0.12.1"
     99 +source = "registry+https://github.com/rust-lang/crates.io-index"
     100 +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
     101 +dependencies = [
     102 + "lock_api",
     103 + "parking_lot_core",
     104 +]
     105 + 
     106 +[[package]]
     107 +name = "parking_lot_core"
     108 +version = "0.9.3"
     109 +source = "registry+https://github.com/rust-lang/crates.io-index"
     110 +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
     111 +dependencies = [
     112 + "cfg-if",
     113 + "libc",
     114 + "redox_syscall",
     115 + "smallvec",
     116 + "windows-sys",
     117 +]
     118 + 
     119 +[[package]]
     120 +name = "proc-macro-crate"
     121 +version = "0.1.5"
     122 +source = "registry+https://github.com/rust-lang/crates.io-index"
     123 +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
     124 +dependencies = [
     125 + "toml",
     126 +]
     127 + 
     128 +[[package]]
     129 +name = "proc-macro2"
     130 +version = "1.0.46"
     131 +source = "registry+https://github.com/rust-lang/crates.io-index"
     132 +checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b"
     133 +dependencies = [
     134 + "unicode-ident",
     135 +]
     136 + 
     137 +[[package]]
     138 +name = "pyo3"
     139 +version = "0.16.6"
     140 +source = "registry+https://github.com/rust-lang/crates.io-index"
     141 +checksum = "0220c44442c9b239dd4357aa856ac468a4f5e1f0df19ddb89b2522952eb4c6ca"
     142 +dependencies = [
     143 + "cfg-if",
     144 + "indoc",
     145 + "libc",
     146 + "parking_lot",
     147 + "pyo3-build-config",
     148 + "pyo3-ffi",
     149 + "pyo3-macros",
     150 + "unindent",
     151 +]
     152 + 
     153 +[[package]]
     154 +name = "pyo3-build-config"
     155 +version = "0.16.6"
     156 +source = "registry+https://github.com/rust-lang/crates.io-index"
     157 +checksum = "9c819d397859445928609d0ec5afc2da5204e0d0f73d6bf9e153b04e83c9cdc2"
     158 +dependencies = [
     159 + "once_cell",
     160 + "target-lexicon",
     161 +]
     162 + 
     163 +[[package]]
     164 +name = "pyo3-ffi"
     165 +version = "0.16.6"
     166 +source = "registry+https://github.com/rust-lang/crates.io-index"
     167 +checksum = "ca882703ab55f54702d7bfe1189b41b0af10272389f04cae38fe4cd56c65f75f"
     168 +dependencies = [
     169 + "libc",
     170 + "pyo3-build-config",
     171 +]
     172 + 
     173 +[[package]]
     174 +name = "pyo3-macros"
     175 +version = "0.16.6"
     176 +source = "registry+https://github.com/rust-lang/crates.io-index"
     177 +checksum = "568749402955ad7be7bad9a09b8593851cd36e549ac90bfd44079cea500f3f21"
     178 +dependencies = [
     179 + "proc-macro2",
     180 + "pyo3-macros-backend",
     181 + "quote",
     182 + "syn",
     183 +]
     184 + 
     185 +[[package]]
     186 +name = "pyo3-macros-backend"
     187 +version = "0.16.6"
     188 +source = "registry+https://github.com/rust-lang/crates.io-index"
     189 +checksum = "611f64e82d98f447787e82b8e7b0ebc681e1eb78fc1252668b2c605ffb4e1eb8"
     190 +dependencies = [
     191 + "proc-macro2",
     192 + "quote",
     193 + "syn",
     194 +]
     195 + 
     196 +[[package]]
     197 +name = "quote"
     198 +version = "1.0.21"
     199 +source = "registry+https://github.com/rust-lang/crates.io-index"
     200 +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
     201 +dependencies = [
     202 + "proc-macro2",
     203 +]
     204 + 
     205 +[[package]]
     206 +name = "redox_syscall"
     207 +version = "0.2.16"
     208 +source = "registry+https://github.com/rust-lang/crates.io-index"
     209 +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
     210 +dependencies = [
     211 + "bitflags",
     212 +]
     213 + 
     214 +[[package]]
     215 +name = "rlers"
     216 +version = "0.0.1"
     217 +dependencies = [
     218 + "byteorder",
     219 + "lazy_static",
     220 + "num_enum",
     221 + "pyo3",
     222 +]
     223 + 
     224 +[[package]]
     225 +name = "scopeguard"
     226 +version = "1.1.0"
     227 +source = "registry+https://github.com/rust-lang/crates.io-index"
     228 +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
     229 + 
     230 +[[package]]
     231 +name = "serde"
     232 +version = "1.0.145"
     233 +source = "registry+https://github.com/rust-lang/crates.io-index"
     234 +checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
     235 + 
     236 +[[package]]
     237 +name = "smallvec"
     238 +version = "1.10.0"
     239 +source = "registry+https://github.com/rust-lang/crates.io-index"
     240 +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
     241 + 
     242 +[[package]]
     243 +name = "syn"
     244 +version = "1.0.102"
     245 +source = "registry+https://github.com/rust-lang/crates.io-index"
     246 +checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
     247 +dependencies = [
     248 + "proc-macro2",
     249 + "quote",
     250 + "unicode-ident",
     251 +]
     252 + 
     253 +[[package]]
     254 +name = "target-lexicon"
     255 +version = "0.12.4"
     256 +source = "registry+https://github.com/rust-lang/crates.io-index"
     257 +checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1"
     258 + 
     259 +[[package]]
     260 +name = "toml"
     261 +version = "0.5.9"
     262 +source = "registry+https://github.com/rust-lang/crates.io-index"
     263 +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
     264 +dependencies = [
     265 + "serde",
     266 +]
     267 + 
     268 +[[package]]
     269 +name = "unicode-ident"
     270 +version = "1.0.5"
     271 +source = "registry+https://github.com/rust-lang/crates.io-index"
     272 +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
     273 + 
     274 +[[package]]
     275 +name = "unindent"
     276 +version = "0.1.10"
     277 +source = "registry+https://github.com/rust-lang/crates.io-index"
     278 +checksum = "58ee9362deb4a96cef4d437d1ad49cffc9b9e92d202b6995674e928ce684f112"
     279 + 
     280 +[[package]]
     281 +name = "windows-sys"
     282 +version = "0.36.1"
     283 +source = "registry+https://github.com/rust-lang/crates.io-index"
     284 +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
     285 +dependencies = [
     286 + "windows_aarch64_msvc",
     287 + "windows_i686_gnu",
     288 + "windows_i686_msvc",
     289 + "windows_x86_64_gnu",
     290 + "windows_x86_64_msvc",
     291 +]
     292 + 
     293 +[[package]]
     294 +name = "windows_aarch64_msvc"
     295 +version = "0.36.1"
     296 +source = "registry+https://github.com/rust-lang/crates.io-index"
     297 +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
     298 + 
     299 +[[package]]
     300 +name = "windows_i686_gnu"
     301 +version = "0.36.1"
     302 +source = "registry+https://github.com/rust-lang/crates.io-index"
     303 +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
     304 + 
     305 +[[package]]
     306 +name = "windows_i686_msvc"
     307 +version = "0.36.1"
     308 +source = "registry+https://github.com/rust-lang/crates.io-index"
     309 +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
     310 + 
     311 +[[package]]
     312 +name = "windows_x86_64_gnu"
     313 +version = "0.36.1"
     314 +source = "registry+https://github.com/rust-lang/crates.io-index"
     315 +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
     316 + 
     317 +[[package]]
     318 +name = "windows_x86_64_msvc"
     319 +version = "0.36.1"
     320 +source = "registry+https://github.com/rust-lang/crates.io-index"
     321 +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
     322 + 
  • ■ ■ ■ ■ ■ ■
    aardwolf/utils/rlers/Cargo.toml
     1 +[package]
     2 +name = "rlers"
     3 +edition = "2021"
     4 +version = "0.0.1"
     5 +authors = ["Sylvain Peyrefitte <[email protected]>", "Tamas Jos"]
     6 +description = "rust RLE decoder with Python bindings"
     7 +repository = ""
     8 +readme = ""
     9 +keywords = ["rdp", "security", "network", "windows"]
     10 +categories = ["network"]
     11 +license = "MIT"
     12 +documentation = ""
     13 + 
     14 +[lib]
     15 +name = "rlers"
     16 +crate-type = ["cdylib"]
     17 +path = "src/rle.rs"
     18 + 
     19 +[dependencies]
     20 +byteorder = "^1.3"
     21 +num_enum = "0.4.3"
     22 +lazy_static = "1.4.0"
     23 +pyo3 = { version = "0.16.5", features = ["extension-module"] }
     24 + 
  • ■ ■ ■ ■ ■
    aardwolf/utils/rlers/__init__.py
     1 + 
  • ■ ■ ■ ■ ■ ■
    aardwolf/utils/rlers/pyproject.toml
     1 +[build-system]
     2 +requires = ["maturin>=0.13,<0.14"]
     3 +build-backend = "maturin"
     4 + 
     5 +[project]
     6 +name = "rlers"
     7 +requires-python = ">=3.11"
     8 +classifiers = [
     9 + "Programming Language :: Rust",
     10 + "Programming Language :: Python :: Implementation :: CPython",
     11 + "Programming Language :: Python :: Implementation :: PyPy",
     12 +]
  • ■ ■ ■ ■ ■ ■
    aardwolf/utils/rlers/src/rle.rs
     1 +/*
     2 +most of the code is taken from https://github.com/citronneur/rdp-rs
     3 +the rest is written by me :)
     4 + 
     5 +MIT License
     6 + 
     7 +Copyright (c) 2019 Sylvain Peyrefitte
     8 + 
     9 +Permission is hereby granted, free of charge, to any person obtaining a copy
     10 +of this software and associated documentation files (the "Software"), to deal
     11 +in the Software without restriction, including without limitation the rights
     12 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     13 +copies of the Software, and to permit persons to whom the Software is
     14 +furnished to do so, subject to the following conditions:
     15 + 
     16 +The above copyright notice and this permission notice shall be included in all
     17 +copies or substantial portions of the Software.
     18 + 
     19 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     20 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     21 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     22 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     23 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     24 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     25 +SOFTWARE.
     26 +*/
     27 + 
     28 +use std::io::{Cursor, Read};
     29 +use byteorder::{ReadBytesExt, LittleEndian};
     30 +use std::io::Error as IoError;
     31 +use std::string::String;
     32 +use num_enum::{TryFromPrimitive, TryFromPrimitiveError};
     33 + 
     34 +use pyo3::prelude::*;
     35 +use pyo3::exceptions::PyTypeError;
     36 +use pyo3::types::PyByteArray;
     37 + 
     38 +use pyo3::ffi::{Py_buffer, PyArg_ParseTuple, PyErr_SetString, PyExc_TypeError, Py_None, PyObject, PyExc_OverflowError};
     39 +use pyo3::{exceptions, pyfunction, pymodule, PyResult, Python, wrap_pyfunction};
     40 +use pyo3::exceptions::PyValueError;
     41 +use pyo3::buffer::PyBuffer;
     42 +use pyo3::types::PyModule;
     43 + 
     44 +#[derive(Debug, Copy, Clone, Eq, PartialEq)]
     45 +pub enum RdpErrorKind {
     46 + /// Unexpected data
     47 + InvalidData,
     48 + /// Respond from server or client is not valid
     49 + InvalidRespond,
     50 + /// Features not implemented
     51 + NotImplemented,
     52 + /// During connection sequence
     53 + /// A security level is negotiated
     54 + /// If no level can be defined a ProtocolNegFailure is emitted
     55 + ProtocolNegFailure,
     56 + /// Protocol automata transition is not expected
     57 + InvalidAutomata,
     58 + /// A security protocol
     59 + /// selected was not handled by rdp-rs
     60 + InvalidProtocol,
     61 + /// All messages in rdp-rs
     62 + /// are based on Message trait
     63 + /// To retrieve the original data we used
     64 + /// a visitor pattern. If the expected
     65 + /// type is not found an InvalidCast error is emited
     66 + InvalidCast,
     67 + /// If an expected value is not equal
     68 + InvalidConst,
     69 + /// During security exchange some
     70 + /// checksum are computed
     71 + InvalidChecksum,
     72 + InvalidOptionalField,
     73 + InvalidSize,
     74 + /// A possible Man In The Middle attack
     75 + /// detected during NLA Authentication
     76 + PossibleMITM,
     77 + /// Some channel or user can be rejected
     78 + /// by server during connection step
     79 + RejectedByServer,
     80 + /// Disconnect receive from server
     81 + Disconnect,
     82 + /// Indicate an unknown field
     83 + Unknown,
     84 + UnexpectedType
     85 +}
     86 + 
     87 +#[derive(Debug)]
     88 +pub struct RdpError {
     89 + /// Kind of error
     90 + kind: RdpErrorKind,
     91 + /// Associated message of the context
     92 + message: String
     93 +}
     94 + 
     95 +impl RdpError {
     96 + /// create a new RDP error
     97 + /// # Example
     98 + /// ```
     99 + /// use rdp::model::error::{RdpError, RdpErrorKind};
     100 + /// let error = RdpError::new(RdpErrorKind::Disconnect, "disconnected");
     101 + /// ```
     102 + pub fn new (kind: RdpErrorKind, message: &str) -> Self {
     103 + RdpError {
     104 + kind,
     105 + message: String::from(message)
     106 + }
     107 + }
     108 + 
     109 + /// Return the kind of error
     110 + ///
     111 + /// # Example
     112 + /// ```
     113 + /// use rdp::model::error::{RdpError, RdpErrorKind};
     114 + /// let error = RdpError::new(RdpErrorKind::Disconnect, "disconnected");
     115 + /// assert_eq!(error.kind(), RdpErrorKind::Disconnect)
     116 + /// ```
     117 + pub fn kind(&self) -> RdpErrorKind {
     118 + self.kind
     119 + }
     120 +}
     121 + 
     122 +#[derive(Debug)]
     123 +pub enum Error {
     124 + /// RDP error
     125 + RdpError(RdpError),
     126 + /// All kind of IO error
     127 + Io(IoError),
     128 + /// try error
     129 + TryError(String)
     130 +}
     131 + 
     132 +/// From IO Error
     133 +impl From<IoError> for Error {
     134 + fn from(e: IoError) -> Self {
     135 + Error::Io(e)
     136 + }
     137 +}
     138 + 
     139 +impl<T: TryFromPrimitive> From<TryFromPrimitiveError<T>> for Error {
     140 + fn from(_: TryFromPrimitiveError<T>) -> Self {
     141 + Error::RdpError(RdpError::new(RdpErrorKind::InvalidCast, "Invalid enum conversion"))
     142 + }
     143 +}
     144 + 
     145 +pub type RdpResult<T> = Result<T, Error>;
     146 + 
     147 +/// Try options is waiting try trait for the next rust
     148 +#[macro_export]
     149 +macro_rules! try_option {
     150 + ($val: expr, $expr: expr) => {
     151 + if let Some(x) = $val {
     152 + Ok(x)
     153 + } else {
     154 + Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidOptionalField, $expr)))
     155 + }
     156 + }
     157 +}
     158 + 
     159 +#[macro_export]
     160 +macro_rules! try_let {
     161 + ($ident: path, $val: expr) => {
     162 + if let $ident(x) = $val {
     163 + Ok(x)
     164 + } else {
     165 + Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidCast, "Invalid Cast")))
     166 + }
     167 + }
     168 +}
     169 + 
     170 + 
     171 + 
     172 +/// All this uncompress code
     173 +/// Are directly inspired from the source code
     174 +/// of rdesktop and diretly port to rust
     175 +/// Need a little bit of refactoring for rust
     176 + 
     177 +fn process_plane(input: &mut dyn Read, width: u32, height: u32, output: &mut [u8]) -> RdpResult<()> {
     178 + let mut indexw;
     179 + let mut indexh= 0;
     180 + let mut code ;
     181 + let mut collen;
     182 + let mut replen;
     183 + let mut color:i8;
     184 + let mut x;
     185 + let mut revcode;
     186 + 
     187 + let mut this_line: u32;
     188 + let mut last_line: u32 = 0;
     189 + 
     190 + while indexh < height {
     191 + let mut out = (width * height * 4) - ((indexh + 1) * width * 4);
     192 + color = 0;
     193 + this_line = out;
     194 + indexw = 0;
     195 + if last_line == 0 {
     196 + while indexw < width {
     197 + code = input.read_u8()?;
     198 + replen = code & 0xf;
     199 + collen = (code >> 4) & 0xf;
     200 + revcode = (replen << 4) | collen;
     201 + if (revcode <= 47) && (revcode >= 16) {
     202 + replen = revcode;
     203 + collen = 0;
     204 + }
     205 + while collen > 0 {
     206 + color = input.read_u8()? as i8;
     207 + output[out as usize] = color as u8;
     208 + out += 4;
     209 + indexw += 1;
     210 + collen -= 1;
     211 + }
     212 + while replen > 0 {
     213 + output[out as usize] = color as u8;
     214 + out += 4;
     215 + indexw += 1;
     216 + replen -= 1;
     217 + }
     218 + }
     219 + }
     220 + else
     221 + {
     222 + while indexw < width {
     223 + code = input.read_u8()?;
     224 + replen = code & 0xf;
     225 + collen = (code >> 4) & 0xf;
     226 + revcode = (replen << 4) | collen;
     227 + if (revcode <= 47) && (revcode >= 16) {
     228 + replen = revcode;
     229 + collen = 0;
     230 + }
     231 + while collen > 0 {
     232 + x = input.read_u8()?;
     233 + if x & 1 != 0{
     234 + x = x >> 1;
     235 + x = x + 1;
     236 + color = -(x as i32) as i8;
     237 + }
     238 + else
     239 + {
     240 + x = x >> 1;
     241 + color = x as i8;
     242 + }
     243 + x = (output[(last_line + (indexw * 4)) as usize] as i32 + color as i32) as u8;
     244 + output[out as usize] = x;
     245 + out += 4;
     246 + indexw += 1;
     247 + collen -= 1;
     248 + }
     249 + while replen > 0 {
     250 + x = (output[(last_line + (indexw * 4)) as usize] as i32 + color as i32) as u8;
     251 + output[out as usize] = x;
     252 + out += 4;
     253 + indexw += 1;
     254 + replen -= 1;
     255 + }
     256 + }
     257 + }
     258 + indexh += 1;
     259 + last_line = this_line;
     260 + }
     261 + Ok(())
     262 +}
     263 + 
     264 +/// Run length encoding decoding function for 32 bpp
     265 +pub fn rle_32_decompress(input: &[u8], width: u32, height: u32, output: &mut [u8]) -> RdpResult<()> {
     266 + let mut input_cursor = Cursor::new(input);
     267 + 
     268 + if input_cursor.read_u8()? != 0x10 {
     269 + return Err(Error::RdpError(RdpError::new(RdpErrorKind::UnexpectedType, "Bad header")))
     270 + }
     271 + 
     272 + process_plane(&mut input_cursor, width, height, &mut output[3..])?;
     273 + process_plane(&mut input_cursor, width, height, &mut output[2..])?;
     274 + process_plane(&mut input_cursor, width, height, &mut output[1..])?;
     275 + process_plane(&mut input_cursor, width, height, &mut output[0..])?;
     276 + 
     277 + Ok(())
     278 +}
     279 + 
     280 +macro_rules! repeat {
     281 + ($expr:expr, $count:expr, $x:expr, $width:expr) => {
     282 + while (($count & !0x7) != 0) && ($x + 8) < $width {
     283 + $expr; $count -= 1; $x += 1;
     284 + $expr; $count -= 1; $x += 1;
     285 + $expr; $count -= 1; $x += 1;
     286 + $expr; $count -= 1; $x += 1;
     287 + $expr; $count -= 1; $x += 1;
     288 + $expr; $count -= 1; $x += 1;
     289 + $expr; $count -= 1; $x += 1;
     290 + $expr; $count -= 1; $x += 1;
     291 + }
     292 + while $count > 0 && $x < $width {
     293 + $expr;
     294 + $count -= 1;
     295 + $x += 1;
     296 + }
     297 + };
     298 +}
     299 + 
     300 +pub fn rle_16_decompress(input: &[u8], width: usize, mut height: usize, output: &mut [u16]) -> RdpResult<()> {
     301 + let mut input_cursor = Cursor::new(input);
     302 + 
     303 + let mut code: u8;
     304 + let mut opcode: u8;
     305 + let mut lastopcode: u8 = 0xFF;
     306 + let mut count: u16;
     307 + let mut offset: u16;
     308 + let mut isfillormix;
     309 + let mut insertmix = false;
     310 + let mut x: usize = width;
     311 + let mut prevline : Option<usize> = None;
     312 + let mut line : Option<usize> = None;
     313 + let mut colour1= 0;
     314 + let mut colour2 = 0;
     315 + let mut mix = 0xffff;
     316 + let mut mask:u8 = 0;
     317 + let mut fom_mask : u8;
     318 + let mut mixmask:u8;
     319 + let mut bicolour = false;
     320 + 
     321 + while (input_cursor.position() as usize) < input.len() {
     322 + fom_mask = 0;
     323 + code = input_cursor.read_u8()?;
     324 + opcode = code >> 4;
     325 + 
     326 + match opcode {
     327 + 0xC | 0xD | 0xE => {
     328 + opcode -= 6;
     329 + count = (code & 0xf) as u16;
     330 + offset = 16;
     331 + }
     332 + 0xF => {
     333 + opcode = code & 0xf;
     334 + if opcode < 9 {
     335 + count = input_cursor.read_u16::<LittleEndian>()?
     336 + } else if opcode < 0xb {
     337 + count = 8
     338 + } else {
     339 + count = 1
     340 + }
     341 + offset = 0;
     342 + }
     343 + _ => {
     344 + opcode >>= 1;
     345 + count = (code & 0x1f) as u16;
     346 + offset = 32;
     347 + }
     348 + }
     349 + 
     350 + if offset != 0 {
     351 + isfillormix = (opcode == 2) || (opcode == 7);
     352 + if count == 0 {
     353 + if isfillormix {
     354 + count = input_cursor.read_u8()? as u16 + 1;
     355 + } else {
     356 + count = input_cursor.read_u8()? as u16 + offset;
     357 + }
     358 + } else if isfillormix {
     359 + count <<= 3;
     360 + }
     361 + }
     362 + 
     363 + match opcode {
     364 + 0 => {
     365 + if lastopcode == opcode && !(x == width && prevline == None) {
     366 + insertmix = true;
     367 + }
     368 + },
     369 + 8 => {
     370 + colour1 = input_cursor.read_u16::<LittleEndian>()?;
     371 + colour2 = input_cursor.read_u16::<LittleEndian>()?;
     372 + },
     373 + 3 => {
     374 + colour2 = input_cursor.read_u16::<LittleEndian>()?;
     375 + },
     376 + 6 | 7 => {
     377 + mix = input_cursor.read_u16::<LittleEndian>()?;
     378 + opcode -= 5;
     379 + }
     380 + 9 => {
     381 + mask = 0x03;
     382 + opcode = 0x02;
     383 + fom_mask = 3;
     384 + },
     385 + 0xa => {
     386 + mask = 0x05;
     387 + opcode = 0x02;
     388 + fom_mask = 5;
     389 + }
     390 + _ => ()
     391 + }
     392 + lastopcode = opcode;
     393 + mixmask = 0;
     394 + 
     395 + while count > 0 {
     396 + if x >= width {
     397 + if height <= 0 {
     398 + return Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidData, "error during decompress")))
     399 + }
     400 + x = 0;
     401 + height -= 1;
     402 + prevline = line;
     403 + line = Some(height * width);
     404 + }
     405 + 
     406 + match opcode {
     407 + 0 => {
     408 + if insertmix {
     409 + if let Some(e) = prevline {
     410 + output[line.unwrap() + x] = output[e + x] ^ mix;
     411 + }
     412 + else {
     413 + output[line.unwrap() + x] = mix;
     414 + }
     415 + insertmix = false;
     416 + count -= 1;
     417 + x += 1;
     418 + }
     419 + 
     420 + if let Some(e) = prevline {
     421 + repeat!(output[line.unwrap() + x] = output[e + x], count, x, width);
     422 + }
     423 + else {
     424 + repeat!(output[line.unwrap() + x] = 0, count, x, width);
     425 + }
     426 + },
     427 + 1 => {
     428 + if let Some(e) = prevline {
     429 + repeat!(output[line.unwrap() + x] = output[e + x] ^ mix, count, x, width);
     430 + }
     431 + else {
     432 + repeat!(output[line.unwrap() + x] = mix, count, x, width);
     433 + }
     434 + },
     435 + 2 => {
     436 + if let Some(e) = prevline {
     437 + repeat!({
     438 + mixmask <<= 1;
     439 + if mixmask == 0 {
     440 + mask = if fom_mask != 0 { fom_mask } else { input_cursor.read_u8()? };
     441 + mixmask = 1;
     442 + }
     443 + if (mask & mixmask) != 0 {
     444 + output[line.unwrap() + x] = output[e + x] ^ mix;
     445 + }
     446 + else {
     447 + output[line.unwrap() + x] = output[e + x];
     448 + }
     449 + }, count, x, width);
     450 + }
     451 + else {
     452 + repeat!({
     453 + mixmask <<= 1;
     454 + if mixmask == 0 {
     455 + mask = if fom_mask != 0 { fom_mask } else { input_cursor.read_u8()? };
     456 + mixmask = 1;
     457 + }
     458 + if (mask & mixmask) != 0 {
     459 + output[line.unwrap() + x] = mix;
     460 + }
     461 + else {
     462 + output[line.unwrap() + x] = 0;
     463 + }
     464 + }, count, x, width);
     465 + }
     466 + },
     467 + 3 => {
     468 + repeat!(output[line.unwrap() + x] = colour2, count, x, width);
     469 + },
     470 + 4 => {
     471 + repeat!(output[line.unwrap() + x] = input_cursor.read_u16::<LittleEndian>()?, count, x, width);
     472 + },
     473 + 8 => {
     474 + repeat!({
     475 + if bicolour {
     476 + output[line.unwrap() + x] = colour2;
     477 + bicolour = false;
     478 + } else {
     479 + output[line.unwrap() + x] = colour1;
     480 + bicolour = true;
     481 + count += 1;
     482 + };
     483 + }, count, x, width);
     484 + },
     485 + 0xd => {
     486 + repeat!(output[line.unwrap() + x] = 0xffff, count, x, width);
     487 + },
     488 + 0xe => {
     489 + repeat!(output[line.unwrap() + x] = 0, count, x, width);
     490 + }
     491 + _ => panic!("opcode")
     492 + }
     493 + }
     494 + }
     495 + 
     496 + Ok(())
     497 +}
     498 + 
     499 +//Changed 2 lines of code for GBR -> RBG conversion: skelsec
     500 +pub fn rgb565torgb32(input: &[u16], width: usize, height: usize) -> Vec<u8> {
     501 + let mut result_32_bpp = vec![0 as u8; width as usize * height as usize * 4];
     502 + for i in 0..height {
     503 + for j in 0..width {
     504 + let index = (i * width + j) as usize;
     505 + let v = input[index];
     506 + result_32_bpp[index * 4 + 3] = 0xff;
     507 + result_32_bpp[index * 4 + 2] = ((((v & 0x1f) * 527) + 23) >> 6) as u8;
     508 + result_32_bpp[index * 4 + 1] = (((((v >> 5) & 0x3f) * 259) + 33) >> 6) as u8;
     509 + result_32_bpp[index * 4] = (((((v >> 11) & 0x1f) * 527) + 23) >> 6) as u8;
     510 + }
     511 + }
     512 + result_32_bpp
     513 +}
     514 + 
     515 + 
     516 + 
     517 + 
     518 +/*
     519 + #########################################################################################################
     520 + #########################################################################################################
     521 + # THE MESS BELOW IS SKELSEC
     522 + #
     523 + #########################################################################################################
     524 + #########################################################################################################
     525 +*/
     526 + 
     527 + 
     528 +fn convert_rgb555_rgb32(decomp_buff: Vec<u8>, decomp_buff_size: usize, dst: &mut Vec<u8>, _dst_size: usize) {
     529 + let mut j = 0;
     530 + for i in (0..decomp_buff_size).step_by(2) {
     531 + let t = ((decomp_buff[i+1] as u16) << 8) + decomp_buff[i] as u16;
     532 + dst[j] = (t >> 8) as u8;
     533 + dst[j+1] = (((t >> 5) & 0b11111) << 3) as u8;
     534 + dst[j+2] = ((t & 0x1F) as u8) << 3;
     535 + dst[j+3] = 0xff;
     536 + j += 4;
     537 + }
     538 +}
     539 + 
     540 +fn convert_rgb565_rgb32(decomp_buff: Vec<u8>, decomp_buff_size: usize, dst: &mut Vec<u8>, _dst_size: usize) {
     541 + let mut j = 0;
     542 + for i in (0..decomp_buff_size).step_by(2) {
     543 + let t = ((decomp_buff[i+1] as u16) << 8) + decomp_buff[i] as u16;
     544 + dst[j] = (t >> 8) as u8;
     545 + dst[j+1] = (((t >> 5) & 0b111111) << 2) as u8;
     546 + dst[j+2] = ((t & 0x1F) as u8) << 3;
     547 + dst[j+3] = 0xff;
     548 + j += 4;
     549 + }
     550 +}
     551 + 
     552 +fn convert_rgb24_rgb32(decomp_buff: Vec<u8>, decomp_buff_size: usize, dst: &mut Vec<u8>, _dst_size: usize) {
     553 + let mut j = 0;
     554 + for i in (0..decomp_buff_size).step_by(3) {
     555 + dst[j] = decomp_buff[i];
     556 + dst[j+1] = decomp_buff[i+1];
     557 + dst[j+2] = decomp_buff[i+2];
     558 + dst[i+3] = 0xff;
     559 + j += 4;
     560 + }
     561 +}
     562 + 
     563 +fn convert_rgbx_rgba(decomp_buff: Vec<u8>, decomp_buff_size: usize, dst: &mut Vec<u8>) {
     564 + for i in (0..decomp_buff_size).step_by(4) {
     565 + dst[i] = decomp_buff[i];
     566 + dst[i+1] = decomp_buff[i+1];
     567 + dst[i+2] = decomp_buff[i+2];
     568 + dst[i+3] = 0xff;
     569 + }
     570 +}
     571 + 
     572 +fn decode_rre(rre_buff: Vec<u8>, rre_buff_size: usize, dst: &mut Vec<u8>, bypp: u16, width: u16, height: u16) -> i16 {
     573 + let dst_size: usize = dst.len();
     574 + let sub_rect_num = ((rre_buff[0] as u32) << 24) + ((rre_buff[1] as u32) << 16) + ((rre_buff[2] as u32) << 8) + rre_buff[3] as u32;
     575 + let sub_rect_num_bytes = sub_rect_num*12;
     576 + let rectangle_pixel_count = width * height;
     577 + let rectangle_size = rectangle_pixel_count * bypp;
     578 + let mut sub_rectangle_pixel_count = 0;
     579 + let mut subrect_color_offset = 0;
     580 + let mut subwidth_bytes = 0;
     581 + let mut subx = 0u16;
     582 + let mut suby = 0u16;
     583 + let mut subwidth = 0u16;
     584 + let mut subheight = 0u16;
     585 + let mut substart = 0u16;
     586 +
     587 + if rectangle_size as usize > dst_size {
     588 + return 1;
     589 + }
     590 + 
     591 + // filling rectangle with default pattern
     592 + for i in (0..rectangle_size).step_by(bypp as usize) {
     593 + dst[i as usize] = rre_buff[4];
     594 + dst[(i+1) as usize] = rre_buff[5];
     595 + dst[(i+2) as usize] = rre_buff[6];
     596 + dst[(i+3) as usize] = 0xff; // alpha channel
     597 + }
     598 +
     599 + //println!("rs dst: {:?}", dst);
     600 + 
     601 + if sub_rect_num*12+8 != rre_buff_size as u32 {
     602 + //println!("sub_rect_num {}", sub_rect_num);
     603 + //println!("boundary: {}", sub_rect_num*12+8);
     604 + //println!("rre_buff_size: {}", rre_buff_size);
     605 + return 1;
     606 + }
     607 + 
     608 + for i in (0..sub_rect_num_bytes).step_by(12) {
     609 + //memo: 12 = 4(RGBX) + subx, suby, subwidth, subheight
     610 + subx = ((rre_buff[(8+4+i) as usize] as u16) << 8) + rre_buff[(8+5+i) as usize] as u16;
     611 + suby = ((rre_buff[(8+6+i) as usize] as u16) << 8) + rre_buff[(8+7+i) as usize] as u16;
     612 + subwidth = ((rre_buff[(8+8+i) as usize] as u16) << 8) + rre_buff[(8+9+i) as usize] as u16;
     613 + subwidth_bytes = subwidth * 4;
     614 + subheight = ((rre_buff[(8+10+i) as usize] as u16) << 8) + rre_buff[(8+11+i) as usize] as u16;
     615 + sub_rectangle_pixel_count = subwidth * subheight;
     616 + subrect_color_offset = 8+i;
     617 +
     618 + for j in 0..sub_rectangle_pixel_count {
     619 + for y in 0..subheight {
     620 + substart = (subx + (suby+y) * width) * bypp;
     621 + if substart > dst_size as u16 || substart + subwidth_bytes > dst_size as u16 {
     622 + return 1;
     623 + }
     624 + 
     625 + for x in (0..subwidth_bytes).step_by(4) {
     626 + dst[(substart+x ) as usize] = rre_buff[(subrect_color_offset ) as usize];
     627 + dst[(substart+x+1) as usize] = rre_buff[(subrect_color_offset+1) as usize];
     628 + dst[(substart+x+2) as usize] = rre_buff[(subrect_color_offset+2) as usize];
     629 + dst[(substart+x+3) as usize] = 0xff; // alpha channel
     630 + }
     631 + }
     632 + }
     633 + }
     634 + return 0;
     635 +}
     636 +
     637 +// *INDENT-ON*
     638 +#[pyfunction]
     639 +#[pyo3(name = "bitmap_decompress")]
     640 +fn bitmap_decompress_wrapper(py: Python<'_>, input: PyBuffer<u8>, width: usize, height: usize, bpp: usize, is_compressed: usize) -> PyResult<&PyByteArray> {
     641 + // actually only handle 32 bpp
     642 + 
     643 + let mut data = input.to_vec(py).unwrap();
     644 +
     645 + if bpp == 32 {
     646 + // 32 bpp is straight forward
     647 + return Ok(
     648 + if is_compressed != 0 {
     649 + let mut result = vec![0 as u8; width as usize * height as usize * 4];
     650 + match rle_32_decompress(&data, width as u32, height as u32, &mut result){
     651 + Err(e) => {
     652 + return Err(PyTypeError::new_err("Decompression Error 32"));
     653 + },
     654 + Ok(x) => {
     655 + let output_as_bytes = PyByteArray::new(py, &result);
     656 + //return Ok(output_as_bytes);
     657 + output_as_bytes
     658 + }
     659 + }
     660 +
     661 + } else {
     662 + let output_as_bytes = PyByteArray::new(py, &data);
     663 + //return Ok(output_as_bytes);
     664 + output_as_bytes
     665 + }
     666 + )
     667 + }
     668 + if bpp == 16 {
     669 + // 16 bpp is more consumer
     670 + if is_compressed != 0 {
     671 + let mut result = vec![0 as u16; width as usize * height as usize * 2];
     672 + let res = match rle_16_decompress(&data, width as usize, height as usize, &mut result){
     673 + Err(e) => {
     674 + return Err(PyTypeError::new_err("Decompression Error 16"));
     675 + },
     676 + Ok(()) => {
     677 + let mut output_buffer = rgb565torgb32(&result, width as usize, height as usize);
     678 + let output_as_bytes = PyByteArray::new(py, &mut output_buffer);
     679 + return Ok(output_as_bytes)
     680 + },
     681 +
     682 + };
     683 + res
     684 +
     685 + } else {
     686 + let mut result = vec![0 as u16; width as usize * height as usize];
     687 + for i in 0..height {
     688 + for j in 0..width {
     689 + let src = (((height - i - 1) * width + j) * 2) as usize;
     690 + result[(i * width + j) as usize] = (data[src + 1] as u16) << 8 | data[src] as u16;
     691 + }
     692 + }
     693 + let mut output_buffer = rgb565torgb32(&result, width as usize, height as usize);
     694 + let output_as_bytes = PyByteArray::new(py, &mut output_buffer);
     695 + return Ok(output_as_bytes)
     696 + };
     697 +
     698 + }
     699 + return Err(PyTypeError::new_err("Unsupported bpp!"));
     700 +}
     701 + 
     702 + 
     703 +#[pyfunction]
     704 +#[pyo3(name = "mask_rgbx")]
     705 +fn mask_rgbx_wrapper(py: Python<'_>, input: PyBuffer<u8>) -> PyResult<&PyByteArray> {
     706 + let mut output_buffer = vec![0 as u8; input.len_bytes() as usize];
     707 + convert_rgbx_rgba(input.to_vec(py).unwrap(), input.len_bytes(), &mut output_buffer);
     708 + return Ok(PyByteArray::new(py, &output_buffer));
     709 +}
     710 + 
     711 +#[pyfunction]
     712 +#[pyo3(name = "decode_rre")]
     713 +fn decode_rre_wrapper(py: Python<'_>, input: PyBuffer<u8>, width: u16, height: u16, bypp: u16) -> PyResult<&PyByteArray> {
     714 + let mut output_buffer = vec![0 as u8; width as usize * height as usize * bypp as usize];
     715 + if decode_rre(input.to_vec(py).unwrap(), input.len_bytes(), &mut output_buffer, bypp, width, height) != 0 {
     716 + return Err(PyTypeError::new_err("Decode failed!"));
     717 + }
     718 + return Ok(PyByteArray::new(py, &output_buffer));
     719 +}
     720 + 
     721 +#[pymodule]
     722 +fn librlers(py: Python<'_>, m: &PyModule) -> PyResult<()> {
     723 + m.add_function(wrap_pyfunction!(bitmap_decompress_wrapper, m)?)?;
     724 + m.add_function(wrap_pyfunction!(mask_rgbx_wrapper, m)?)?;
     725 + m.add_function(wrap_pyfunction!(decode_rre_wrapper, m)?)?;
     726 + Ok(())
     727 +}
     728 + 
     729 +
  • ■ ■ ■ ■ ■ ■
    aardwolf/vncconnection.py
    skipped 37 lines
    38 38  except ImportError:
    39 39   logger.debug('No Qt installed! Converting to qt will not work')
    40 40   
    41  -import rle
     41 +import librlers
    42 42   
    43 43  # https://datatracker.ietf.org/doc/html/rfc6143
    44 44   
    skipped 603 lines
    648 648   
    649 649   async def __reader_loop(self):
    650 650   try:
    651  - ctr = 0
    652 651   while True:
    653 652   msgtype = await self.__reader.readexactly(1)
    654 653   msgtype = ord(msgtype)
    skipped 8 lines
    663 662   if encoding == RAW_ENCODING:
    664 663   try:
    665 664   data = await self.__reader.readexactly(width*height*self.bypp)
    666  - image = bytes(width * height * self.bypp)
    667  - rle.mask_rgbx(image, data)
    668  - image = Image.frombytes('RGBA', [width, height], image)
     665 + data = librlers.mask_rgbx(data)
     666 + image = Image.frombytes('RGBA', [width, height], bytes(data))
    669 667   await self.__send_rect(x,y,width, height, image)
    670 668   except Exception as e:
    671 669   traceback.print_exc()
    skipped 25 lines
    697 695   data = await self.__reader.readexactly(subrect_size)
    698 696   raw_data += data
    699 697  
    700  - raw_out = bytes(width*height*self.bypp)
    701  - rle.decode_rre(raw_out, raw_data, width, height, self.bypp)
     698 + raw_out = librlers.decode_rre(raw_data, width, height, self.bypp)
     699 + raw_out = bytes(raw_out)
    702 700  
    703 701   rect = Image.frombytes('RGBA', [width, height], raw_out)
    704 702   await self.__send_rect(x,y, width, height, rect)
    skipped 75 lines
    780 778   async def set_encodings(self, list_of_encodings = [2, 1, 0]):
    781 779   """Sends a setencoding message to the server, indicating the types of image encodings we support"""
    782 780   try:
     781 + if list_of_encodings is None:
     782 + list_of_encodings = [2, 1, 0]
    783 783   enc_encodings = b''
    784 784   for encoding in list_of_encodings:
    785 785   enc_encodings += encoding.to_bytes(4, byteorder = 'big', signed = True)
    skipped 59 lines
  • ■ ■ ■ ■ ■ ■
    setup.py
    1 1  from setuptools import setup, find_packages
    2  -from distutils.core import setup, Extension
     2 +from setuptools_rust import Binding, RustExtension
    3 3  import re
    4  -import platform
    5 4   
    6 5  VERSIONFILE="aardwolf/_version.py"
    7 6  verstrline = open(VERSIONFILE, "rt").read()
    8 7  VSRE = r"^__version__ = ['\"]([^'\"]*)['\"]"
    9 8  mo = re.search(VSRE, verstrline, re.M)
    10 9  if mo:
    11  - verstr = mo.group(1)
     10 + verstr = mo.group(1)
    12 11  else:
    13  - raise RuntimeError("Unable to find version string in %s." % (VERSIONFILE,))
    14  - 
    15  -rle_module = Extension('rle',
    16  - define_macros = [('MAJOR_VERSION', '1'), ('MINOR_VERSION', '0')],
    17  - include_dirs = ['/usr/local/include'],
    18  - library_dirs = ['/usr/local/lib'],
    19  - sources = ['aardwolf/utils/rle/rle.c']
    20  -)
    21  - 
     12 + raise RuntimeError("Unable to find version string in %s." % (VERSIONFILE,))
     13 +print(find_packages())
    22 14  setup(
    23 15   # Application name:
    24 16   name="aardwolf",
    skipped 23 lines
    48 40   # long_description=open("README.txt").read(),
    49 41   python_requires='>=3.7',
    50 42  
    51  - ext_modules = [rle_module],
     43 + rust_extensions=[RustExtension("librlers", path= "aardwolf/utils/rlers/Cargo.toml", binding=Binding.PyO3)],
    52 44   
    53 45   
    54 46   install_requires=[
    skipped 9 lines
    64 56   'arc4>=0.3.0', #faster than cryptodome
    65 57   'Pillow>=9.0.0',
    66 58   ],
    67  -
    68 59  
    69 60   classifiers=[
    70 61   "Programming Language :: Python :: 3.8",
    skipped 9 lines
Please wait...
Page is in error, reload to recover