Projects STRLCPY aardwolf Commits e6e55f17
🤬
  • ■ ■ ■ ■ ■ ■
    aardwolf/utils/rle/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 = "aardwolf"
     7 +version = "0.1.0"
     8 +dependencies = [
     9 + "bufstream",
     10 + "byteorder",
     11 + "lazy_static",
     12 + "pyo3",
     13 +]
     14 + 
     15 +[[package]]
     16 +name = "autocfg"
     17 +version = "1.1.0"
     18 +source = "registry+https://github.com/rust-lang/crates.io-index"
     19 +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
     20 + 
     21 +[[package]]
     22 +name = "bitflags"
     23 +version = "1.3.2"
     24 +source = "registry+https://github.com/rust-lang/crates.io-index"
     25 +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
     26 + 
     27 +[[package]]
     28 +name = "bufstream"
     29 +version = "0.1.4"
     30 +source = "registry+https://github.com/rust-lang/crates.io-index"
     31 +checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8"
     32 + 
     33 +[[package]]
     34 +name = "byteorder"
     35 +version = "1.4.3"
     36 +source = "registry+https://github.com/rust-lang/crates.io-index"
     37 +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
     38 + 
     39 +[[package]]
     40 +name = "cfg-if"
     41 +version = "1.0.0"
     42 +source = "registry+https://github.com/rust-lang/crates.io-index"
     43 +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
     44 + 
     45 +[[package]]
     46 +name = "indoc"
     47 +version = "1.0.7"
     48 +source = "registry+https://github.com/rust-lang/crates.io-index"
     49 +checksum = "adab1eaa3408fb7f0c777a73e7465fd5656136fc93b670eb6df3c88c2c1344e3"
     50 + 
     51 +[[package]]
     52 +name = "lazy_static"
     53 +version = "1.4.0"
     54 +source = "registry+https://github.com/rust-lang/crates.io-index"
     55 +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
     56 + 
     57 +[[package]]
     58 +name = "libc"
     59 +version = "0.2.132"
     60 +source = "registry+https://github.com/rust-lang/crates.io-index"
     61 +checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
     62 + 
     63 +[[package]]
     64 +name = "lock_api"
     65 +version = "0.4.8"
     66 +source = "registry+https://github.com/rust-lang/crates.io-index"
     67 +checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390"
     68 +dependencies = [
     69 + "autocfg",
     70 + "scopeguard",
     71 +]
     72 + 
     73 +[[package]]
     74 +name = "once_cell"
     75 +version = "1.14.0"
     76 +source = "registry+https://github.com/rust-lang/crates.io-index"
     77 +checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
     78 + 
     79 +[[package]]
     80 +name = "parking_lot"
     81 +version = "0.12.1"
     82 +source = "registry+https://github.com/rust-lang/crates.io-index"
     83 +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
     84 +dependencies = [
     85 + "lock_api",
     86 + "parking_lot_core",
     87 +]
     88 + 
     89 +[[package]]
     90 +name = "parking_lot_core"
     91 +version = "0.9.3"
     92 +source = "registry+https://github.com/rust-lang/crates.io-index"
     93 +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
     94 +dependencies = [
     95 + "cfg-if",
     96 + "libc",
     97 + "redox_syscall",
     98 + "smallvec",
     99 + "windows-sys",
     100 +]
     101 + 
     102 +[[package]]
     103 +name = "proc-macro2"
     104 +version = "1.0.43"
     105 +source = "registry+https://github.com/rust-lang/crates.io-index"
     106 +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
     107 +dependencies = [
     108 + "unicode-ident",
     109 +]
     110 + 
     111 +[[package]]
     112 +name = "pyo3"
     113 +version = "0.16.6"
     114 +source = "registry+https://github.com/rust-lang/crates.io-index"
     115 +checksum = "0220c44442c9b239dd4357aa856ac468a4f5e1f0df19ddb89b2522952eb4c6ca"
     116 +dependencies = [
     117 + "cfg-if",
     118 + "indoc",
     119 + "libc",
     120 + "parking_lot",
     121 + "pyo3-build-config",
     122 + "pyo3-ffi",
     123 + "pyo3-macros",
     124 + "unindent",
     125 +]
     126 + 
     127 +[[package]]
     128 +name = "pyo3-build-config"
     129 +version = "0.16.6"
     130 +source = "registry+https://github.com/rust-lang/crates.io-index"
     131 +checksum = "9c819d397859445928609d0ec5afc2da5204e0d0f73d6bf9e153b04e83c9cdc2"
     132 +dependencies = [
     133 + "once_cell",
     134 + "target-lexicon",
     135 +]
     136 + 
     137 +[[package]]
     138 +name = "pyo3-ffi"
     139 +version = "0.16.6"
     140 +source = "registry+https://github.com/rust-lang/crates.io-index"
     141 +checksum = "ca882703ab55f54702d7bfe1189b41b0af10272389f04cae38fe4cd56c65f75f"
     142 +dependencies = [
     143 + "libc",
     144 + "pyo3-build-config",
     145 +]
     146 + 
     147 +[[package]]
     148 +name = "pyo3-macros"
     149 +version = "0.16.6"
     150 +source = "registry+https://github.com/rust-lang/crates.io-index"
     151 +checksum = "568749402955ad7be7bad9a09b8593851cd36e549ac90bfd44079cea500f3f21"
     152 +dependencies = [
     153 + "proc-macro2",
     154 + "pyo3-macros-backend",
     155 + "quote",
     156 + "syn",
     157 +]
     158 + 
     159 +[[package]]
     160 +name = "pyo3-macros-backend"
     161 +version = "0.16.6"
     162 +source = "registry+https://github.com/rust-lang/crates.io-index"
     163 +checksum = "611f64e82d98f447787e82b8e7b0ebc681e1eb78fc1252668b2c605ffb4e1eb8"
     164 +dependencies = [
     165 + "proc-macro2",
     166 + "quote",
     167 + "syn",
     168 +]
     169 + 
     170 +[[package]]
     171 +name = "quote"
     172 +version = "1.0.21"
     173 +source = "registry+https://github.com/rust-lang/crates.io-index"
     174 +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
     175 +dependencies = [
     176 + "proc-macro2",
     177 +]
     178 + 
     179 +[[package]]
     180 +name = "redox_syscall"
     181 +version = "0.2.16"
     182 +source = "registry+https://github.com/rust-lang/crates.io-index"
     183 +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
     184 +dependencies = [
     185 + "bitflags",
     186 +]
     187 + 
     188 +[[package]]
     189 +name = "scopeguard"
     190 +version = "1.1.0"
     191 +source = "registry+https://github.com/rust-lang/crates.io-index"
     192 +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
     193 + 
     194 +[[package]]
     195 +name = "smallvec"
     196 +version = "1.9.0"
     197 +source = "registry+https://github.com/rust-lang/crates.io-index"
     198 +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
     199 + 
     200 +[[package]]
     201 +name = "syn"
     202 +version = "1.0.99"
     203 +source = "registry+https://github.com/rust-lang/crates.io-index"
     204 +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
     205 +dependencies = [
     206 + "proc-macro2",
     207 + "quote",
     208 + "unicode-ident",
     209 +]
     210 + 
     211 +[[package]]
     212 +name = "target-lexicon"
     213 +version = "0.12.4"
     214 +source = "registry+https://github.com/rust-lang/crates.io-index"
     215 +checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1"
     216 + 
     217 +[[package]]
     218 +name = "unicode-ident"
     219 +version = "1.0.3"
     220 +source = "registry+https://github.com/rust-lang/crates.io-index"
     221 +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
     222 + 
     223 +[[package]]
     224 +name = "unindent"
     225 +version = "0.1.10"
     226 +source = "registry+https://github.com/rust-lang/crates.io-index"
     227 +checksum = "58ee9362deb4a96cef4d437d1ad49cffc9b9e92d202b6995674e928ce684f112"
     228 + 
     229 +[[package]]
     230 +name = "windows-sys"
     231 +version = "0.36.1"
     232 +source = "registry+https://github.com/rust-lang/crates.io-index"
     233 +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
     234 +dependencies = [
     235 + "windows_aarch64_msvc",
     236 + "windows_i686_gnu",
     237 + "windows_i686_msvc",
     238 + "windows_x86_64_gnu",
     239 + "windows_x86_64_msvc",
     240 +]
     241 + 
     242 +[[package]]
     243 +name = "windows_aarch64_msvc"
     244 +version = "0.36.1"
     245 +source = "registry+https://github.com/rust-lang/crates.io-index"
     246 +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
     247 + 
     248 +[[package]]
     249 +name = "windows_i686_gnu"
     250 +version = "0.36.1"
     251 +source = "registry+https://github.com/rust-lang/crates.io-index"
     252 +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
     253 + 
     254 +[[package]]
     255 +name = "windows_i686_msvc"
     256 +version = "0.36.1"
     257 +source = "registry+https://github.com/rust-lang/crates.io-index"
     258 +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
     259 + 
     260 +[[package]]
     261 +name = "windows_x86_64_gnu"
     262 +version = "0.36.1"
     263 +source = "registry+https://github.com/rust-lang/crates.io-index"
     264 +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
     265 + 
     266 +[[package]]
     267 +name = "windows_x86_64_msvc"
     268 +version = "0.36.1"
     269 +source = "registry+https://github.com/rust-lang/crates.io-index"
     270 +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
     271 + 
  • ■ ■ ■ ■ ■ ■
    aardwolf/utils/rle/Cargo.toml
     1 +[package]
     2 +name = "aardwolf"
     3 +version = "0.1.0"
     4 +edition = "2021"
     5 + 
     6 +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
     7 +[lib]
     8 +name = "rle"
     9 +crate-type = ["cdylib"]
     10 +path = 'src/rle2.rs'
     11 + 
     12 +[dependencies]
     13 +lazy_static = "1.4.0"
     14 +pyo3 = { version = "0.16.5", features = ["extension-module"] }
     15 +byteorder = "^1.3"
     16 +bufstream = "0.1"
  • ■ ■ ■ ■ ■ ■
    aardwolf/utils/rle/pyproject.toml
     1 +[build-system]
     2 +requires = ["maturin>=0.13,<0.14"]
     3 +build-backend = "maturin"
     4 + 
     5 +[project]
     6 +name = "rle"
     7 +requires-python = ">=3.11"
     8 +classifiers = [
     9 + "Programming Language :: Rust",
     10 + "Programming Language :: Python :: Implementation :: CPython",
     11 + "Programming Language :: Python :: Implementation :: PyPy",
     12 +]
     13 + 
  • ■ ■ ■ ■ ■ ■
    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/src/rle.rs
     1 +/*
     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 +/*
     22 + Added few modifications:
     23 + The code now ALWAYS returns RGB32 format regardless of input bpp. Makes life easier on upper levels.
     24 + The code also takes non-compressed input (and a flag that indicates wether it's compressed or not.)
     25 + Non-compressed data will be only converted to RGB32.
     26 + There are some out-of-bounds write possibilities in the RRE decoder.
     27 + 
     28 + Mod author: Tamas Jos @skelsec
     29 +*/
     30 + 
     31 +/*
     32 + Portation to Rust:
     33 + The original C code is now ported to Rust code.
     34 + The functions bitmap_decompress2, mask_rgbx, decode_rre, their wrapper and all the functions that
     35 + get called by those one are tested and are working.
     36 + The rest is not tested yet so that it may contain any logical bugs.
     37 + However, all functions are syntactically correct and do compile.
     38 + 
     39 + I am the author and tester of this code. I am not the sole owner or the algorithm developer.
     40 + The sole owner is Tamas Jos @skelsec.
     41 + 
     42 + Mod author: Julien Schminke @ProgrammerSkill
     43 + Fiverr: ProgrammerSkill
     44 + */
     45 + 
     46 +use std::ffi::CString;
     47 +use std::slice;
     48 + 
     49 +use pyo3::prelude::*;
     50 +use pyo3::exceptions::PyTypeError;
     51 +use pyo3::types::PyByteArray;
     52 + 
     53 +use pyo3::ffi::{Py_buffer, PyArg_ParseTuple, PyErr_SetString, PyExc_TypeError, Py_None, PyObject};
     54 +use pyo3::{exceptions, pyfunction, pymodule, PyResult, Python, wrap_pyfunction};
     55 +use pyo3::buffer::PyBuffer;
     56 +use pyo3::types::PyModule;
     57 + 
     58 +#[macro_use] extern crate lazy_static;
     59 + 
     60 +macro_rules! cval {
     61 + ($p:expr, $p_index:expr) => ({
     62 + let c = $p[$p_index];
     63 + $p_index += 1;
     64 + c
     65 + })
     66 +}
     67 + 
     68 +macro_rules! cval2 {
     69 + ($p:expr, $p_index:expr, $v:expr) => ({
     70 + if cfg!(need_align) && cfg!(l_endian) { // NEED_ALIGN & L_ENDIAN
     71 + $v = $p[$p_index] as u16;
     72 + $p_index += 1;
     73 + $v |= ($p[$p_index] as u16) << 8;
     74 + $p_index += 1;
     75 + } else if cfg!(need_align) { // NEED_ALIGN & !L_ENDIAN
     76 + $v = ($p[$p_index] as u16) << 8;
     77 + $p_index += 1;
     78 + $v |= $p[$p_index] as u16;
     79 + $p_index += 1;
     80 + } else { // !NEED_ALIGN
     81 + $v = (($p[$p_index] as u16) << 8) + $p[$p_index+1] as u16;
     82 + $p_index += 2;
     83 + }
     84 + })
     85 +}
     86 + 
     87 +macro_rules! unroll8 {
     88 + ($exp:block) => ($exp $exp $exp $exp $exp $exp $exp $exp)
     89 +}
     90 + 
     91 +macro_rules! repeat {
     92 + ($statement:block, $count:expr, $x:expr, $width:expr) => (
     93 + while ($count & !0x7) != 0 && ($x + 8 < $width) {
     94 + unroll8!({$statement; $count -= 1; $x += 1;});
     95 + }
     96 + 
     97 + while ($count > 0) && ($x < $width) {
     98 + $statement;
     99 + $count -= 1;
     100 + $x += 1;
     101 + }
     102 + );
     103 +}
     104 + 
     105 +macro_rules! mask_update {
     106 + ($mixmask:expr, $fom_mask:expr, $input_index:expr, $input:expr, $mask:expr) => {
     107 + $mixmask <<= 1;
     108 + if $mixmask == 0 {
     109 + $mask = if $fom_mask != 0 {
     110 + $fom_mask
     111 + } else {
     112 + cval!($input, $input_index)
     113 + };
     114 + $mixmask = 1;
     115 + }
     116 + }
     117 +}
     118 + 
     119 + 
     120 +// 1 byte bitmap decompress
     121 +fn bitmap_decompress1(mut output: &mut Vec<u8>, width: i16, mut height: i16, input: &mut Vec<u8>, _size: usize) -> bool {
     122 + let mut prevline_index = None;
     123 + let mut line_index = None;
     124 + let mut opcode: i16;
     125 + let mut count: i16;
     126 + let mut offset: i16 = 0;
     127 + let mut isfillormix: bool;
     128 + let mut x = width;
     129 + let mut lastopcode = -1;
     130 + let mut insertmix = false;
     131 + let mut bicolour = false;
     132 + let mut code: u8;
     133 + let mut colour1 = 0u8;
     134 + let mut colour2 = 0u8;
     135 + let mut mixmask: u8;
     136 + let mut mask = 0u8;
     137 + let mut mix = 0xffu8;
     138 + let mut fom_mask = 0;
     139 + 
     140 + let mut input_index = 0;
     141 + while input_index < input.len() {
     142 + fom_mask = 0;
     143 + code = cval!(input, input_index);
     144 + opcode = (code >> 4) as i16;
     145 + 
     146 + // Handle different opcode forms
     147 + match opcode {
     148 + 0xc | 0xd | 0xe => {
     149 + opcode -= 6;
     150 + count = (code & 0xf) as i16;
     151 + offset = 16;
     152 + },
     153 + 0xf => {
     154 + opcode = (code & 0xf) as i16;
     155 + if opcode < 9 {
     156 + count = cval!(input, input_index) as i16;
     157 + count |= (cval!(input, input_index) as i16) << 8
     158 + } else {
     159 + count = if opcode < 0xb { 8 } else { 1 };
     160 + }
     161 + offset = 0;
     162 + }
     163 + _ => {
     164 + opcode >>= 1;
     165 + count = (code & 0x1f) as i16;
     166 + offset = 32;
     167 + },
     168 + }
     169 + // Handle strange cases for counts
     170 + if offset != 0 {
     171 + isfillormix = opcode == 2 || opcode == 7;
     172 + if count == 0 {
     173 + count = if isfillormix {
     174 + cval!(input, input_index) as i16 + 1
     175 + } else {
     176 + cval!(input, input_index) as i16 + offset
     177 + }
     178 + } else if isfillormix {
     179 + count <<= 3;
     180 + }
     181 + }
     182 + 
     183 + // Read preliminary data
     184 + 
     185 + // Bicolour
     186 + if opcode == 8 {
     187 + colour1 = cval!(input, input_index);
     188 + }
     189 + 
     190 + match opcode {
     191 + 0 => {
     192 + // Fill
     193 + if lastopcode == opcode && !(x == width && prevline_index.is_none()) {
     194 + insertmix = true;
     195 + }
     196 + },
     197 + 3 => {
     198 + // Colour
     199 + colour2 = cval!(input, input_index);
     200 + },
     201 + 6 | 7 => {
     202 + // 6 = SetMix/Mix
     203 + // 7 = SetMix/FillOrMix
     204 + mix = cval!(input, input_index);
     205 + opcode -= 5;
     206 + },
     207 + 9 => {
     208 + // FillOrMix_1
     209 + mask = 0x03;
     210 + opcode = 0x02;
     211 + fom_mask = 3;
     212 + },
     213 + 0x0a => {
     214 + // FillOrMix_2
     215 + mask = 0x05;
     216 + opcode = 0x02;
     217 + fom_mask = 5;
     218 + },
     219 + _ => (),
     220 + }
     221 + lastopcode = opcode;
     222 + mixmask = 0;
     223 + // Output body
     224 + while count > 0 {
     225 + if x >= width {
     226 + if height <= 0 {
     227 + return false;
     228 + }
     229 + x = 0;
     230 + height -= 1;
     231 + prevline_index = line_index;
     232 + line_index = Some(height * width);
     233 + }
     234 + match opcode {
     235 + 0 => {
     236 + // Fill
     237 + if insertmix {
     238 + if prevline_index.is_none() {
     239 + output[(line_index.unwrap()+x) as usize] = mix;
     240 + } else {
     241 + output[(line_index.unwrap()+x) as usize] = output[prevline_index.unwrap() as usize]^mix;
     242 + }
     243 + insertmix = false;
     244 + count -= 1;
     245 + x += 1;
     246 + }
     247 + if prevline_index.is_none() {
     248 + repeat!({output[(line_index.unwrap()+x) as usize] = 0;}, count, x, width);
     249 + } else {
     250 + repeat!({output[(line_index.unwrap()+x) as usize] = output[(prevline_index.unwrap() + x) as usize];}, count, x, width);
     251 + }
     252 + },
     253 + 1 => {
     254 + // Mix
     255 + if prevline_index.is_none() {
     256 + repeat!({output[(line_index.unwrap()+x) as usize] = mix;}, count, x, width);
     257 + } else {
     258 + repeat!({output[(line_index.unwrap()+x) as usize] = output[(((prevline_index.unwrap()) + x) ^ mix as i16) as usize];}, count, x, width);
     259 + }
     260 + },
     261 + 2 => {
     262 + //Fill or Mix
     263 + if prevline_index.is_none() {
     264 + repeat!({
     265 + mask_update!(mixmask, fom_mask, input_index, input, mask);
     266 + if (mask & mixmask) != 0 {
     267 + output[(line_index.unwrap()+x) as usize] = mix
     268 + } else {
     269 + output[(line_index.unwrap()+x) as usize] = 0;
     270 + }
     271 + }, count, x, width);
     272 + } else {
     273 + repeat!({
     274 + mask_update!(mixmask, fom_mask, input_index, input, mask);
     275 + if (mask & mixmask) != 0 {
     276 + output[(line_index.unwrap()+x) as usize] = output[((prevline_index.unwrap()+x) ^ mix as i16) as usize];
     277 + } else {
     278 + output[(line_index.unwrap()+x) as usize] = output[(prevline_index.unwrap()+x) as usize]
     279 + }
     280 + }, count, x, width);
     281 + }
     282 + },
     283 + 3 => { // Colour
     284 + repeat!({output[(line_index.unwrap()+x) as usize] = colour2;}, count, x, width);
     285 + },
     286 + 4 => { // Copy
     287 + repeat!({output[(line_index.unwrap()+x) as usize] = cval!(input, input_index);}, count, x, width);
     288 + },
     289 + 8 => { // Bicolour
     290 + repeat!({
     291 + if bicolour {
     292 + output[(line_index.unwrap()+x) as usize] = colour2;
     293 + bicolour = false;
     294 + } else {
     295 + output[(line_index.unwrap()+x) as usize] = colour1;
     296 + bicolour = true;
     297 + count += 1;
     298 + }
     299 + }, count, x, width);
     300 + },
     301 + 0xd => { // White
     302 + repeat!({output[(line_index.unwrap()+x) as usize] = 0xff;}, count, x, width);
     303 + },
     304 + 0xe => { // Black
     305 + repeat!({output[(line_index.unwrap()+x) as usize] = 0;} , count, x, width);
     306 + },
     307 + _ => {
     308 + return false;
     309 + },
     310 + }
     311 + }
     312 + }
     313 + true
     314 +}
     315 + 
     316 + 
     317 +// 2 byte bitmap decompress
     318 +fn bitmap_decompress2(mut output: &mut Vec<u8>, width: i16, mut height: i16, input: &mut Vec<u8>, _size: usize) -> bool {
     319 + let mut prevline_index = None;
     320 + let mut line_index = None;
     321 + let mut opcode: i16;
     322 + let mut count: i16;
     323 + let mut offset: i16 = 0;
     324 + let mut isfillormix: bool;
     325 + let mut x = width;
     326 + let mut lastopcode = -1;
     327 + let mut insertmix = false;
     328 + let mut bicolour = false;
     329 + let mut code: u8;
     330 + let mut colour1 = 0u16;
     331 + let mut colour2 = 0u16;
     332 + let mut mixmask: u8;
     333 + let mut mask = 0u8;
     334 + let mut mix = 0xffffu16;
     335 + let mut fom_mask = 0;
     336 + 
     337 + let mut input_index = 0;
     338 + let mut output_u16_clone: Vec<u16> = output
     339 + .chunks_exact(2)
     340 + .into_iter()
     341 + .map(|a| u16::from_ne_bytes([a[0], a[1]]))
     342 + .collect();
     343 + 
     344 + while input_index < input.len() {
     345 + fom_mask = 0;
     346 + code = cval!(input, input_index);
     347 + opcode = (code >> 4) as i16;
     348 + 
     349 + // Handle different opcode forms
     350 + match opcode {
     351 + 0xc | 0xd | 0xe => {
     352 + opcode -= 6;
     353 + count = (code & 0xf) as i16;
     354 + offset = 16;
     355 + },
     356 + 0xf => {
     357 + opcode = (code & 0xf) as i16;
     358 + if opcode < 9 {
     359 + count = cval!(input, input_index) as i16;
     360 + count |= (cval!(input, input_index) as i16) << 8
     361 + } else {
     362 + count = if opcode < 0xb { 8 } else { 1 };
     363 + }
     364 + offset = 0;
     365 + }
     366 + _ => {
     367 + opcode >>= 1;
     368 + count = (code & 0x1f) as i16;
     369 + offset = 32;
     370 + },
     371 + }
     372 + // Handle strange cases for counts
     373 + if offset != 0 {
     374 + isfillormix = opcode == 2 || opcode == 7;
     375 + if count == 0 {
     376 + count = if isfillormix {
     377 + cval!(input, input_index) as i16 + 1
     378 + } else {
     379 + cval!(input, input_index) as i16 + offset
     380 + };
     381 +
     382 + } else if isfillormix {
     383 + count <<= 3;
     384 + }
     385 + }
     386 + 
     387 + // Read preliminary data
     388 + 
     389 + // Bicolour
     390 + if opcode == 8 {
     391 + cval2!(input, input_index, colour1);
     392 + }
     393 + 
     394 + match opcode {
     395 + 0 => {
     396 + // Fill
     397 + if lastopcode == opcode && !(x == width && prevline_index.is_none()) {
     398 + insertmix = true;
     399 + }
     400 + },
     401 + 3 => {
     402 + // Colour
     403 + cval2!(input, input_index, colour2);
     404 + },
     405 + 6 | 7 => {
     406 + // 6 = SetMix/Mix
     407 + // 7 = SetMix/FillOrMix
     408 + cval2!(input, input_index, mix);
     409 + opcode = -5;
     410 + },
     411 + 9 => {
     412 + // FillOrMix_1
     413 + mask = 0x03;
     414 + opcode = 0x02;
     415 + fom_mask = 3;
     416 + },
     417 + 0x0a => {
     418 + // FillOrMix_2
     419 + mask = 0x05;
     420 + opcode = 0x02;
     421 + fom_mask = 5;
     422 + },
     423 + _ => (),
     424 + }
     425 + lastopcode = opcode;
     426 + mixmask = 0;
     427 + 
     428 + // Output body
     429 + while count > 0 {
     430 + if x >= width {
     431 + if height <= 0 {
     432 + for i in 0..output_u16_clone.len() {
     433 + output[i*2 ] = (output_u16_clone[i] >> 8 ) as u8;
     434 + output[i*2+1] = (output_u16_clone[i] | 0x00ff) as u8;
     435 + 
     436 + }
     437 + return false;
     438 + }
     439 + x = 0;
     440 + height -= 1;
     441 + prevline_index = line_index;
     442 + line_index = Some(height * width);
     443 + }
     444 + 
     445 + match opcode {
     446 + 0 => {
     447 + // Fill
     448 + if insertmix {
     449 + 
     450 + if prevline_index.is_none() {
     451 + output_u16_clone[(line_index.unwrap()+x) as usize] = mix;
     452 + } else {
     453 + output_u16_clone[(line_index.unwrap()+x) as usize] = output_u16_clone[(prevline_index.unwrap()+x) as usize] ^ mix;
     454 + }
     455 + insertmix = false;
     456 + count -= 1;
     457 + x += 1;
     458 + }
     459 + if prevline_index.is_none() {
     460 + repeat!({output_u16_clone[(line_index.unwrap()+x) as usize] = 0}, count, x, width);
     461 + } else {
     462 + repeat!({output_u16_clone[(line_index.unwrap()+x) as usize] = output_u16_clone[(prevline_index.unwrap() + x) as usize];}, count, x, width);
     463 + }
     464 + },
     465 + 1 => {
     466 + // Mix
     467 + if prevline_index.is_none() {
     468 + repeat!({output_u16_clone[(line_index.unwrap()+x) as usize] = mix}, count, x, width);
     469 + } else {
     470 + repeat!({output_u16_clone[(line_index.unwrap()+x) as usize] = output_u16_clone[(prevline_index.unwrap()+x) as usize] ^ mix}, count, x, width);
     471 + }
     472 + },
     473 + 2 => {
     474 + //Fill or Mix
     475 + if prevline_index.is_none() {
     476 + repeat!({
     477 + mask_update!(mixmask, fom_mask, input_index, input, mask);
     478 + if (mask & mixmask) != 0 {
     479 + output_u16_clone[(line_index.unwrap()+x) as usize] = mix;
     480 + } else {
     481 + output_u16_clone[(line_index.unwrap()+x) as usize] = 0;
     482 + }
     483 + }, count, x, width);
     484 + } else {
     485 + repeat!({
     486 + mask_update!(mixmask, fom_mask, input_index, input, mask);
     487 + if (mask & mixmask) != 0 {
     488 + output_u16_clone[(line_index.unwrap()+x) as usize] = output_u16_clone[(prevline_index.unwrap()+x) as usize] ^ mix;
     489 + } else {
     490 + output_u16_clone[(line_index.unwrap()+x) as usize] = output_u16_clone[(prevline_index.unwrap()+x) as usize];
     491 + }
     492 + }, count, x, width);
     493 + }
     494 + },
     495 + 3 => { // Colour
     496 + repeat!({output_u16_clone[(line_index.unwrap()+x) as usize] = colour2}, count, x, width); //TODO unsicher mit colour2
     497 + },
     498 + 4 => { // Copy
     499 + repeat!({cval2!(input, input_index, output_u16_clone[(line_index.unwrap()+x) as usize])}, count, x, width);
     500 + },
     501 + 8 => { // Bicolour
     502 + repeat!({
     503 + if bicolour {
     504 + output_u16_clone[(line_index.unwrap()+x) as usize] = colour2;
     505 + bicolour = false;
     506 + } else {
     507 + output_u16_clone[(line_index.unwrap()+x) as usize] = colour1;
     508 + bicolour = true;
     509 + count += 1;
     510 + }
     511 + }, count, x, width);
     512 + },
     513 + 0xd => { // White
     514 + repeat!({output_u16_clone[(line_index.unwrap()+x) as usize] = 0xffff;}, count, x, width);
     515 + },
     516 + 0xe => { // Black
     517 + repeat!({output_u16_clone[(line_index.unwrap()+x) as usize] = 0;} , count, x, width);
     518 + },
     519 + _ => {
     520 + for i in 0..output_u16_clone.len() {
     521 + output[i*2 ] = (output_u16_clone[i] >> 8 ) as u8;
     522 + output[i*2+1] = (output_u16_clone[i] & 0x00ff) as u8;
     523 + 
     524 + }
     525 + return false;
     526 + },
     527 + }
     528 + }
     529 + }
     530 + for i in 0..output_u16_clone.len() {
     531 + output[i*2 ] = (output_u16_clone[i] >> 8 ) as u8;
     532 + output[i*2+1] = (output_u16_clone[i] & 0x00ff) as u8;
     533 + 
     534 + }
     535 + true
     536 +}
     537 + 
     538 +// 3 byte bitmap decompress
     539 +fn bitmap_decompress3(mut output: &mut Vec<u8>, width: i16, mut height: i16, input: &mut Vec<u8>, _size: usize) -> bool {
     540 + let mut prevline_index = None;
     541 + let mut line_index = None;
     542 + let mut opcode: i16;
     543 + let mut count: i16;
     544 + let mut offset: i16 = 0;
     545 + let mut isfillormix: bool;
     546 + let mut x = width;
     547 + let mut lastopcode = -1;
     548 + let mut insertmix = false;
     549 + let mut bicolour = false;
     550 + let mut code: u8;
     551 + let mut colour1 = [0u8, 0, 0];
     552 + let mut colour2 = [0u8, 0, 0];
     553 + let mut mixmask: u8;
     554 + let mut mask = 0u8;
     555 + let mut mix = [0xffu8, 0xff, 0xff];
     556 + let mut fom_mask = 0;
     557 + 
     558 + let mut input_index = 0;
     559 + while input_index < input.len() {
     560 + fom_mask = 0;
     561 + code = cval!(input, input_index);
     562 + opcode = (code >> 4) as i16;
     563 + 
     564 + match opcode {
     565 + 0xc | 0xd | 0xe => {
     566 + opcode -= 6;
     567 + count = (code & 0xf) as i16;
     568 + offset = 16;
     569 + },
     570 + 0xf => {
     571 + opcode = (code & 0xf) as i16;
     572 + if opcode < 9 {
     573 + count = cval!(input, input_index) as i16;
     574 + count |= (cval!(input, input_index) as i16) << 8
     575 + } else {
     576 + count = if opcode < 0xb { 8 } else { 1 };
     577 + }
     578 + offset = 0;
     579 + }
     580 + _ => {
     581 + opcode >>= 1;
     582 + count = (code & 0x1f) as i16;
     583 + offset = 32;
     584 + },
     585 + }
     586 + // Handle strange cases for counts
     587 + if offset != 0 {
     588 + isfillormix = opcode == 2 || opcode == 7;
     589 + if count == 0 {
     590 + count = if isfillormix {
     591 + cval!(input, input_index) as i16 + 1
     592 + } else {
     593 + cval!(input, input_index) as i16 + offset
     594 + }
     595 + } else if isfillormix {
     596 + count <<= 3;
     597 + }
     598 + }
     599 + 
     600 + // Read preliminary data
     601 + 
     602 + // Bicolour
     603 + if opcode == 8 {
     604 + colour1[0] = cval!(input, input_index);
     605 + colour1[1] = cval!(input, input_index);
     606 + colour1[2] = cval!(input, input_index);
     607 + }
     608 + 
     609 + match opcode {
     610 + 0 => {
     611 + // Fill
     612 + if lastopcode == opcode && !(x == width && prevline_index.is_none()) {
     613 + insertmix = true;
     614 + }
     615 + },
     616 + 3 => {
     617 + // Colour
     618 + colour2[0] = cval!(input, input_index);
     619 + colour2[1] = cval!(input, input_index);
     620 + colour2[2] = cval!(input, input_index);
     621 + },
     622 + 6 | 7 => {
     623 + // 6 = SetMix/Mix
     624 + // 7 = SetMix/FillOrMix
     625 + mix[0] = cval!(input, input_index);
     626 + mix[1] = cval!(input, input_index);
     627 + mix[2] = cval!(input, input_index);
     628 + opcode = -5;
     629 + },
     630 + 9 => {
     631 + // FillOrMix_1
     632 + mask = 0x03;
     633 + opcode = 0x02;
     634 + fom_mask = 3;
     635 + },
     636 + 0x0a => {
     637 + // FillOrMix_2
     638 + mask = 0x05;
     639 + opcode = 0x02;
     640 + fom_mask = 5;
     641 + },
     642 + _ => (),
     643 + }
     644 + lastopcode = opcode;
     645 + mixmask = 0;
     646 + // Output body
     647 + while count > 0 {
     648 + if x >= width {
     649 + if height <= 0 {
     650 + return false;
     651 + }
     652 + x = 0;
     653 + height -= 1;
     654 + prevline_index = line_index;
     655 + line_index = Some(height * width * 3);
     656 + }
     657 + match opcode {
     658 + 0 => {
     659 + // Fill
     660 + if insertmix {
     661 + if prevline_index.is_none() {
     662 + output[(line_index.unwrap()+x*3 ) as usize] = mix[0];
     663 + output[(line_index.unwrap()+x*3+1) as usize] = mix[1];
     664 + output[(line_index.unwrap()+x*3+2) as usize] = mix[2];
     665 + } else {
     666 + output[(line_index.unwrap()+x*3 ) as usize] = output[(prevline_index.unwrap()+x*3 ) as usize] ^ mix[0];
     667 + output[(line_index.unwrap()+x*3+1) as usize] = output[(prevline_index.unwrap()+x*3+1) as usize] ^ mix[1];
     668 + output[(line_index.unwrap()+x*3+2) as usize] = output[(prevline_index.unwrap()+x*3+2) as usize] ^ mix[2];
     669 + }
     670 + insertmix = false;
     671 + count -= 1;
     672 + x += 1;
     673 + }
     674 + if prevline_index.is_none() {
     675 + repeat!({
     676 + output[(line_index.unwrap()+x*3 ) as usize] = 0;
     677 + output[(line_index.unwrap()+x*3+1) as usize] = 0;
     678 + output[(line_index.unwrap()+x*3+2) as usize] = 0;
     679 + }, count, x, width);
     680 + } else {
     681 + repeat!({
     682 + output[(line_index.unwrap()+x*3 ) as usize] = output[(prevline_index.unwrap()+x*3 ) as usize];
     683 + output[(line_index.unwrap()+x*3+1) as usize] = output[(prevline_index.unwrap()+x*3+1) as usize];
     684 + output[(line_index.unwrap()+x*3+2) as usize] = output[(prevline_index.unwrap()+x*3+2) as usize];
     685 + }, count, x, width);
     686 + }
     687 + },
     688 + 1 => {
     689 + // Mix
     690 + if prevline_index.is_none() {
     691 + repeat!({
     692 + output[(line_index.unwrap()+x*3 ) as usize] = mix[0];
     693 + output[(line_index.unwrap()+x*3+1) as usize] = mix[1];
     694 + output[(line_index.unwrap()+x*3+2) as usize] = mix[2];
     695 + }, count, x, width);
     696 + } else {
     697 + repeat!({
     698 + output[(line_index.unwrap()+x*3 ) as usize] = output[(prevline_index.unwrap()+x*3 ) as usize] ^ mix[0];
     699 + output[(line_index.unwrap()+x*3+1) as usize] = output[(prevline_index.unwrap()+x*3+1) as usize] ^ mix[1];
     700 + output[(line_index.unwrap()+x*3+2) as usize] = output[(prevline_index.unwrap()+x*3+2) as usize] ^ mix[2];
     701 + }, count, x, width);
     702 + }
     703 + },
     704 + 2 => {
     705 + //Fill or Mix
     706 + if prevline_index.is_none() {
     707 + repeat!({
     708 + mask_update!(mixmask, fom_mask, input_index, input, mask);
     709 + if (mask & mixmask) != 0 {
     710 + output[(line_index.unwrap()+x*3 ) as usize] = mix[0];
     711 + output[(line_index.unwrap()+x*3+1) as usize] = mix[1];
     712 + output[(line_index.unwrap()+x*3+2) as usize] = mix[2];
     713 + } else {
     714 + output[(line_index.unwrap()+x*3 ) as usize] = 0;
     715 + output[(line_index.unwrap()+x*3+1) as usize] = 0;
     716 + output[(line_index.unwrap()+x*3+2) as usize] = 0;
     717 + }
     718 + }, count, x, width);
     719 + } else {
     720 + repeat!({
     721 + mask_update!(mixmask, fom_mask, input_index, input, mask);
     722 + if (mask & mixmask) != 0 {
     723 + output[(line_index.unwrap()+x*3 ) as usize] = output[(prevline_index.unwrap()+x*3 ) as usize] ^ mix[0];
     724 + output[(line_index.unwrap()+x*3+1) as usize] = output[(prevline_index.unwrap()+x*3+1) as usize] ^ mix[1];
     725 + output[(line_index.unwrap()+x*3+2) as usize] = output[(prevline_index.unwrap()+x*3+2) as usize] ^ mix[2];
     726 + } else {
     727 + output[(line_index.unwrap()+x*3 ) as usize] = output[(prevline_index.unwrap()+x*3 ) as usize];
     728 + output[(line_index.unwrap()+x*3+1) as usize] = output[(prevline_index.unwrap()+x*3+1) as usize];
     729 + output[(line_index.unwrap()+x*3+2) as usize] = output[(prevline_index.unwrap()+x*3+2) as usize];
     730 + }
     731 + }, count, x, width);
     732 + }
     733 + },
     734 + 3 => { // Colour
     735 + repeat!({
     736 + output[(line_index.unwrap()+x*3 ) as usize] = colour2[0];
     737 + output[(line_index.unwrap()+x*3+1) as usize] = colour2[1];
     738 + output[(line_index.unwrap()+x*3+2) as usize] = colour2[2];
     739 + }, count, x, width);
     740 + },
     741 + 4 => { // Copy
     742 + repeat!({
     743 + output[(line_index.unwrap()+x*3 ) as usize] = cval!(input, input_index);
     744 + output[(line_index.unwrap()+x*3+1) as usize] = cval!(input, input_index);
     745 + output[(line_index.unwrap()+x*3+2) as usize] = cval!(input, input_index);
     746 + }, count, x, width);
     747 + },
     748 + 8 => { // Bicolour
     749 + repeat!({
     750 + if bicolour {
     751 + output[(line_index.unwrap()+x*3 ) as usize] = colour2[0];
     752 + output[(line_index.unwrap()+x*3+1) as usize] = colour2[1];
     753 + output[(line_index.unwrap()+x*3+2) as usize] = colour2[2];
     754 + bicolour = false;
     755 + } else {
     756 + output[(line_index.unwrap()+x*3 ) as usize] = colour1[0];
     757 + output[(line_index.unwrap()+x*3+1) as usize] = colour1[1];
     758 + output[(line_index.unwrap()+x*3+2) as usize] = colour1[2];
     759 + bicolour = true;
     760 + count += 1;
     761 + }
     762 + }, count, x, width);
     763 + },
     764 + 0xd => { // White
     765 + repeat!({
     766 + output[(line_index.unwrap()+x*3 ) as usize] = 0xff;
     767 + output[(line_index.unwrap()+x*3+1) as usize] = 0xff;
     768 + output[(line_index.unwrap()+x*3+2) as usize] = 0xff;
     769 + }, count, x, width);
     770 + },
     771 + 0xe => { // Black
     772 + repeat!({
     773 + output[(line_index.unwrap()+x*3 ) as usize] = 0;
     774 + output[(line_index.unwrap()+x*3+1) as usize] = 0;
     775 + output[(line_index.unwrap()+x*3+2) as usize] = 0;
     776 + }, count, x, width);
     777 + },
     778 + _ => {
     779 + return false;
     780 + },
     781 + }
     782 + }
     783 + }
     784 + true
     785 +}
     786 + 
     787 +fn process_plane(input: &Vec<u8>, width: i16, height: i16, mut output: &mut Vec<u8>, _size: usize) -> usize {
     788 + let mut indexw;
     789 + let mut indexh = 0;
     790 + let mut code;
     791 + let mut collen;
     792 + let mut replen;
     793 + let mut color;
     794 + let mut x: u8;
     795 + let mut revcode;
     796 + let mut last_line_index = 0;
     797 + let mut this_line_index = 0;
     798 + let mut org_output_index = 0;
     799 + let mut output_index = 0;
     800 + let mut input_index = 0;
     801 + 
     802 + while indexh < height {
     803 + output_index = ((org_output_index + width * height * 4) - ((indexh + 1) * width * 4)) as usize;
     804 + color = 0;
     805 + this_line_index = output_index;
     806 + indexw = 0;
     807 + if last_line_index == 0 {
     808 + while indexw < width {
     809 + code = cval!(input, input_index);
     810 + replen = code & 0xf;
     811 + collen = (code >> 4) & 0xf;
     812 + revcode = (replen << 4) | collen;
     813 + if revcode <= 47 && revcode >= 16 {
     814 + replen = revcode;
     815 + collen = 0;
     816 + }
     817 + while collen > 0 {
     818 + color = cval!(input, input_index);
     819 + output[output_index] = color;
     820 + output_index += 4;
     821 + indexw += 1;
     822 + collen -= 1;
     823 + }
     824 + while replen > 0 {
     825 + output[output_index] = color;
     826 + output_index += 4;
     827 + indexw += 1;
     828 + collen -= 1;
     829 + }
     830 + }
     831 + } else {
     832 + while indexw < width {
     833 + code = cval!(input, input_index);
     834 + replen = code & 0xf;
     835 + collen = (code >> 4) & 0xf;
     836 + revcode = (replen << 4) | collen;
     837 + if revcode <= 47 && revcode >= 16 {
     838 + replen = revcode;
     839 + collen = 0;
     840 + }
     841 + while collen > 0 {
     842 + x = cval!(input, input_index);
     843 + if x & 1 != 0 {
     844 + x >>= 1;
     845 + x += 1;
     846 + color -= x;
     847 + } else {
     848 + x >>= 1;
     849 + color = x;
     850 + }
     851 + x = output[last_line_index * 4] + color;
     852 + output[output_index] = x;
     853 + output_index += 4;
     854 + indexw += 1;
     855 + collen -= 1;
     856 + }
     857 + while replen > 0 {
     858 + x = output[last_line_index * 4] + color;
     859 + output[output_index] = x;
     860 + output_index += 4;
     861 + indexw += 1;
     862 + replen -= 1;
     863 + }
     864 + }
     865 + }
     866 + indexh += 1;
     867 + last_line_index = this_line_index;
     868 + }
     869 + return input_index;
     870 + 
     871 +}
     872 + 
     873 +fn bitmap_decompress4(output: &mut Vec<u8>, width: i16, height: i16, input: &mut Vec<u8>, size: usize) -> bool {
     874 + let code;
     875 + let mut bytes_pro;
     876 + let mut total_pro;
     877 + let mut input_index = 0;
     878 + 
     879 + code = cval!(input, input_index);
     880 + if code != 0x10 {
     881 + return false;
     882 + }
     883 + total_pro = 1;
     884 + bytes_pro = process_plane(&input, width, height, &mut output[3..].to_vec(), size - total_pro);
     885 + total_pro += bytes_pro;
     886 + input[0] += bytes_pro as u8;
     887 + bytes_pro = process_plane(&input, width, height, &mut output[2..].to_vec(), size - total_pro);
     888 + total_pro += bytes_pro;
     889 + input[0] += bytes_pro as u8;
     890 + bytes_pro = process_plane(&input, width, height, &mut output[1..].to_vec(), size - total_pro);
     891 + total_pro += bytes_pro;
     892 + input[0] += bytes_pro as u8;
     893 + bytes_pro = process_plane(&input, width, height, &mut output[0..].to_vec(), size - total_pro);
     894 + total_pro += bytes_pro;
     895 + size == total_pro
     896 +}
     897 + 
     898 +fn bitmap_decompress(output: &mut Vec<u8>, width: i16, height: i16, input: &mut Vec<u8>, size: usize, bpp: usize) -> bool {
     899 + let mut rv = false;
     900 + match bpp {
     901 + 1 => rv = bitmap_decompress1(output, width, height, input, size),
     902 + 2 => rv = bitmap_decompress2(output, width, height, input, size),
     903 + 3 => rv = bitmap_decompress3(output, width, height, input, size),
     904 + 4 => rv = bitmap_decompress4(output, width, height, input, size),
     905 + _ => ()
     906 + }
     907 + rv
     908 +}
     909 + 
     910 +fn convert_rgb555_rgb32(decomp_buff: Vec<u8>, decomp_buff_size: usize, dst: &mut Vec<u8>, _dst_size: usize) {
     911 + let mut j = 0;
     912 + for i in (0..decomp_buff_size).step_by(2) {
     913 + let t = ((decomp_buff[i+1] as u16) << 8) + decomp_buff[i] as u16;
     914 + dst[j] = (t >> 8) as u8;
     915 + dst[j+1] = (((t >> 5) & 0b11111) << 3) as u8;
     916 + dst[j+2] = ((t & 0x1F) as u8) << 3;
     917 + dst[j+3] = 0xff;
     918 + j += 4;
     919 + }
     920 +}
     921 + 
     922 +fn convert_rgb565_rgb32(decomp_buff: Vec<u8>, decomp_buff_size: usize, dst: &mut Vec<u8>, _dst_size: usize) {
     923 + let mut j = 0;
     924 + for i in (0..decomp_buff_size).step_by(2) {
     925 + let t = ((decomp_buff[i+1] as u16) << 8) + decomp_buff[i] as u16;
     926 + dst[j] = (t >> 8) as u8;
     927 + dst[j+1] = (((t >> 5) & 0b111111) << 2) as u8;
     928 + dst[j+2] = ((t & 0x1F) as u8) << 3;
     929 + dst[j+3] = 0xff;
     930 + j += 4;
     931 + }
     932 +}
     933 + 
     934 +fn convert_rgb24_rgb32(decomp_buff: Vec<u8>, decomp_buff_size: usize, dst: &mut Vec<u8>, _dst_size: usize) {
     935 + let mut j = 0;
     936 + for i in (0..decomp_buff_size).step_by(3) {
     937 + dst[j] = decomp_buff[i];
     938 + dst[j+1] = decomp_buff[i+1];
     939 + dst[j+2] = decomp_buff[i+2];
     940 + dst[i+3] = 0xff;
     941 + j += 4;
     942 + }
     943 +}
     944 + 
     945 +fn convert_rgbx_rgba(decomp_buff: Vec<u8>, decomp_buff_size: usize, dst: &mut Vec<u8>, _dst_size: usize) {
     946 + for i in (0..decomp_buff_size).step_by(4) {
     947 + dst[i] = decomp_buff[i];
     948 + dst[i+1] = decomp_buff[i+1];
     949 + dst[i+2] = decomp_buff[i+2];
     950 + dst[i+3] = 0xff;
     951 + }
     952 +}
     953 + 
     954 +fn decode_rre(rre_buff: Vec<u8>, rre_buff_size: usize, dst: &mut Vec<u8>, dst_size: usize, bypp: u16, width: u16, height: u16) -> i16 {
     955 + 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;
     956 + let sub_rect_num_bytes = sub_rect_num*12;
     957 + let rectangle_pixel_count = width * height;
     958 + let rectangle_size = rectangle_pixel_count * bypp;
     959 + let mut sub_rectangle_pixel_count = 0;
     960 + let mut subrect_color_offset = 0;
     961 + let mut subwidth_bytes = 0;
     962 + let mut subx = 0u16;
     963 + let mut suby = 0u16;
     964 + let mut subwidth = 0u16;
     965 + let mut subheight = 0u16;
     966 + let mut substart = 0u16;
     967 +
     968 + if rectangle_size as usize > dst_size {
     969 + return 1;
     970 + }
     971 + 
     972 + // filling rectangle with default pattern
     973 + for i in (0..rectangle_size).step_by(bypp as usize) {
     974 + dst[i as usize] = rre_buff[4];
     975 + dst[(i+1) as usize] = rre_buff[5];
     976 + dst[(i+2) as usize] = rre_buff[6];
     977 + dst[(i+3) as usize] = 0xff; // alpha channel
     978 + }
     979 +
     980 + //println!("rs dst: {:?}", dst);
     981 + 
     982 + if sub_rect_num*12+8 != rre_buff_size as u32 {
     983 + println!("sub_rect_num {}", sub_rect_num);
     984 + println!("boundary: {}", sub_rect_num*12+8);
     985 + println!("rre_buff_size: {}", rre_buff_size);
     986 + return 1;
     987 + }
     988 + 
     989 + for i in (0..sub_rect_num_bytes).step_by(12) {
     990 + //memo: 12 = 4(RGBX) + subx, suby, subwidth, subheight
     991 + subx = ((rre_buff[(8+4+i) as usize] as u16) << 8) + rre_buff[(8+5+i) as usize] as u16;
     992 + suby = ((rre_buff[(8+6+i) as usize] as u16) << 8) + rre_buff[(8+7+i) as usize] as u16;
     993 + subwidth = ((rre_buff[(8+8+i) as usize] as u16) << 8) + rre_buff[(8+9+i) as usize] as u16;
     994 + subwidth_bytes = subwidth * 4;
     995 + subheight = ((rre_buff[(8+10+i) as usize] as u16) << 8) + rre_buff[(8+11+i) as usize] as u16;
     996 + sub_rectangle_pixel_count = subwidth * subheight;
     997 + subrect_color_offset = 8+i;
     998 +
     999 + for j in 0..sub_rectangle_pixel_count {
     1000 + for y in 0..subheight {
     1001 + substart = (subx + (suby+y) * width) * bypp;
     1002 + if substart > dst_size as u16 || substart + subwidth_bytes > dst_size as u16 {
     1003 + return 1;
     1004 + }
     1005 + 
     1006 + for x in (0..subwidth_bytes).step_by(4) {
     1007 + dst[(substart+x ) as usize] = rre_buff[(subrect_color_offset ) as usize];
     1008 + dst[(substart+x+1) as usize] = rre_buff[(subrect_color_offset+1) as usize];
     1009 + dst[(substart+x+2) as usize] = rre_buff[(subrect_color_offset+2) as usize];
     1010 + dst[(substart+x+3) as usize] = 0xff; // alpha channel
     1011 + }
     1012 + }
     1013 + }
     1014 + }
     1015 + return 0;
     1016 +}
     1017 + 
     1018 +// *INDENT-ON*
     1019 +#[pyfunction]
     1020 +#[pyo3(name = "bitmap_decompress")]
     1021 +fn bitmap_decompress_wrapper(py: Python<'_>, output: PyBuffer<u8>, width: usize, height: usize, input: PyBuffer<u8>, bitsperpixel: usize, bpp: usize, is_compressed: usize) -> PyResult<&PyByteArray> {
     1022 + let mut decomp_size = 0usize;
     1023 + let mut decomp_buffer;
     1024 + 
     1025 + if is_compressed != 0 {
     1026 + decomp_size = width * height * bpp;
     1027 + decomp_buffer = vec![0; decomp_size];
     1028 + 
     1029 + if !bitmap_decompress(&mut decomp_buffer, width as i16, height as i16, &mut input.to_vec(py).unwrap(), input.len_bytes(), bpp) {
     1030 + return Err(PyTypeError::new_err("Decompression Error"));
     1031 + }
     1032 + } else {
     1033 + decomp_size = input.len_bytes();
     1034 + decomp_buffer = input.to_vec(py).unwrap();
     1035 + }
     1036 + 
     1037 + let mut output_buffer = output.to_vec(py).unwrap();
     1038 + 
     1039 + match bitsperpixel {
     1040 + 15 => convert_rgb555_rgb32(decomp_buffer, decomp_size, &mut output_buffer, output.len_bytes()),
     1041 + 16 => convert_rgb565_rgb32(decomp_buffer, decomp_size, &mut output_buffer, output.len_bytes()),
     1042 + 24 => convert_rgb24_rgb32(decomp_buffer, decomp_size, &mut output_buffer, output.len_bytes()),
     1043 + 32 | _ => (),
     1044 + }
     1045 + 
     1046 + let output_as_bytes = PyByteArray::new(py, &output_buffer);
     1047 + return Ok(output_as_bytes);
     1048 +}
     1049 + 
     1050 +#[pyfunction]
     1051 +#[pyo3(name = "mask_rgbx")]
     1052 +fn mask_rgbx_wrapper(py: Python<'_>, output: PyBuffer<u8>, input: PyBuffer<u8>) -> PyResult<&PyByteArray> {
     1053 + let mut output_buffer = output.to_vec(py).unwrap();
     1054 + convert_rgbx_rgba(input.to_vec(py).unwrap(), input.len_bytes(), &mut output_buffer, output.len_bytes());
     1055 + return Ok(PyByteArray::new(py, &output_buffer));
     1056 +}
     1057 + 
     1058 +#[pyfunction]
     1059 +#[pyo3(name = "decode_rre")]
     1060 +fn decode_rre_wrapper(py: Python<'_>, output: PyBuffer<u8>, input: PyBuffer<u8>, width: u16, height: u16, bypp: u16) -> PyResult<&PyByteArray> {
     1061 + let mut output_buffer = output.to_vec(py).unwrap();
     1062 + if decode_rre(input.to_vec(py).unwrap(), input.len_bytes(), &mut output_buffer, output.len_bytes(), bypp, width, height) != 0 {
     1063 + return Err(PyTypeError::new_err("Decode failed!"));
     1064 + }
     1065 + return Ok(PyByteArray::new(py, &output_buffer));
     1066 +}
     1067 + 
     1068 +#[pymodule]
     1069 +fn rle(py: Python<'_>, m: &PyModule) -> PyResult<()> {
     1070 + m.add_function(wrap_pyfunction!(bitmap_decompress_wrapper, m)?)?;
     1071 + m.add_function(wrap_pyfunction!(mask_rgbx_wrapper, m)?)?;
     1072 + m.add_function(wrap_pyfunction!(decode_rre_wrapper, m)?)?;
     1073 + Ok(())
     1074 +}
     1075 + 
     1076 + 
     1077 + 
  • ■ ■ ■ ■ ■ ■
    aardwolf/utils/rle/src/rle2.rs
     1 +use std::io::{Cursor, Read, Error};
     2 +use byteorder::{ReadBytesExt, LittleEndian};
     3 +//use std::ffi::CString;
     4 + 
     5 +//use pyo3::prelude::*;
     6 +use pyo3::exceptions::PyTypeError;
     7 +use pyo3::types::PyByteArray;
     8 + 
     9 +use pyo3::ffi::{Py_buffer, PyArg_ParseTuple, PyErr_SetString, PyExc_TypeError, Py_None, PyObject};
     10 +use pyo3::{exceptions, pyfunction, pymodule, PyResult, Python, wrap_pyfunction};
     11 +use pyo3::buffer::PyBuffer;
     12 +use pyo3::types::PyModule;
     13 + 
     14 +/// All this uncompress code
     15 +/// Are directly inspired from the source code
     16 +/// of rdesktop and diretly port to rust
     17 +/// Need a little bit of refactoring for rust
     18 + 
     19 +fn process_plane(input: &mut dyn Read, width: u32, height: u32, output: &mut [u8]) -> Result<T, Error> {
     20 + let mut indexw;
     21 + let mut indexh= 0;
     22 + let mut code ;
     23 + let mut collen;
     24 + let mut replen;
     25 + let mut color:i8;
     26 + let mut x;
     27 + let mut revcode;
     28 + 
     29 + let mut this_line: u32;
     30 + let mut last_line: u32 = 0;
     31 + 
     32 + while indexh < height {
     33 + let mut out = (width * height * 4) - ((indexh + 1) * width * 4);
     34 + color = 0;
     35 + this_line = out;
     36 + indexw = 0;
     37 + if last_line == 0 {
     38 + while indexw < width {
     39 + code = input.read_u8()?;
     40 + replen = code & 0xf;
     41 + collen = (code >> 4) & 0xf;
     42 + revcode = (replen << 4) | collen;
     43 + if (revcode <= 47) && (revcode >= 16) {
     44 + replen = revcode;
     45 + collen = 0;
     46 + }
     47 + while collen > 0 {
     48 + color = input.read_u8()? as i8;
     49 + output[out as usize] = color as u8;
     50 + out += 4;
     51 + indexw += 1;
     52 + collen -= 1;
     53 + }
     54 + while replen > 0 {
     55 + output[out as usize] = color as u8;
     56 + out += 4;
     57 + indexw += 1;
     58 + replen -= 1;
     59 + }
     60 + }
     61 + }
     62 + else
     63 + {
     64 + while indexw < width {
     65 + code = input.read_u8()?;
     66 + replen = code & 0xf;
     67 + collen = (code >> 4) & 0xf;
     68 + revcode = (replen << 4) | collen;
     69 + if (revcode <= 47) && (revcode >= 16) {
     70 + replen = revcode;
     71 + collen = 0;
     72 + }
     73 + while collen > 0 {
     74 + x = input.read_u8()?;
     75 + if x & 1 != 0{
     76 + x = x >> 1;
     77 + x = x + 1;
     78 + color = -(x as i32) as i8;
     79 + }
     80 + else
     81 + {
     82 + x = x >> 1;
     83 + color = x as i8;
     84 + }
     85 + x = (output[(last_line + (indexw * 4)) as usize] as i32 + color as i32) as u8;
     86 + output[out as usize] = x;
     87 + out += 4;
     88 + indexw += 1;
     89 + collen -= 1;
     90 + }
     91 + while replen > 0 {
     92 + x = (output[(last_line + (indexw * 4)) as usize] as i32 + color as i32) as u8;
     93 + output[out as usize] = x;
     94 + out += 4;
     95 + indexw += 1;
     96 + replen -= 1;
     97 + }
     98 + }
     99 + }
     100 + indexh += 1;
     101 + last_line = this_line;
     102 + }
     103 + Ok(())
     104 +}
     105 + 
     106 +/// Run length encoding decoding function for 32 bpp
     107 +pub fn rle_32_decompress(input: &[u8], width: u32, height: u32, output: &mut [u8]) -> Result<T, Error> {
     108 + let mut input_cursor = Cursor::new(input);
     109 + 
     110 + if input_cursor.read_u8()? != 0x10 {
     111 + Err(());
     112 + }
     113 + 
     114 + process_plane(&mut input_cursor, width, height, &mut output[3..])?;
     115 + process_plane(&mut input_cursor, width, height, &mut output[2..])?;
     116 + process_plane(&mut input_cursor, width, height, &mut output[1..])?;
     117 + process_plane(&mut input_cursor, width, height, &mut output[0..])?;
     118 + 
     119 + Ok(())
     120 +}
     121 + 
     122 +macro_rules! repeat {
     123 + ($expr:expr, $count:expr, $x:expr, $width:expr) => {
     124 + while (($count & !0x7) != 0) && ($x + 8) < $width {
     125 + $expr; $count -= 1; $x += 1;
     126 + $expr; $count -= 1; $x += 1;
     127 + $expr; $count -= 1; $x += 1;
     128 + $expr; $count -= 1; $x += 1;
     129 + $expr; $count -= 1; $x += 1;
     130 + $expr; $count -= 1; $x += 1;
     131 + $expr; $count -= 1; $x += 1;
     132 + $expr; $count -= 1; $x += 1;
     133 + }
     134 + while $count > 0 && $x < $width {
     135 + $expr;
     136 + $count -= 1;
     137 + $x += 1;
     138 + }
     139 + };
     140 +}
     141 + 
     142 +pub fn rle_16_decompress(input: &[u8], width: usize, mut height: usize, output: &mut [u16]) -> Result<T, Error> {
     143 + let mut input_cursor = Cursor::new(input);
     144 + 
     145 + let mut code: u8;
     146 + let mut opcode: u8;
     147 + let mut lastopcode: u8 = 0xFF;
     148 + let mut count: u16;
     149 + let mut offset: u16;
     150 + let mut isfillormix;
     151 + let mut insertmix = false;
     152 + let mut x: usize = width;
     153 + let mut prevline : Option<usize> = None;
     154 + let mut line : Option<usize> = None;
     155 + let mut colour1= 0;
     156 + let mut colour2 = 0;
     157 + let mut mix = 0xffff;
     158 + let mut mask:u8 = 0;
     159 + let mut fom_mask : u8;
     160 + let mut mixmask:u8;
     161 + let mut bicolour = false;
     162 + 
     163 + while (input_cursor.position() as usize) < input.len() {
     164 + fom_mask = 0;
     165 + code = input_cursor.read_u8()?;
     166 + opcode = code >> 4;
     167 + 
     168 + match opcode {
     169 + 0xC | 0xD | 0xE => {
     170 + opcode -= 6;
     171 + count = (code & 0xf) as u16;
     172 + offset = 16;
     173 + }
     174 + 0xF => {
     175 + opcode = code & 0xf;
     176 + if opcode < 9 {
     177 + count = input_cursor.read_u16::<LittleEndian>()?
     178 + } else if opcode < 0xb {
     179 + count = 8
     180 + } else {
     181 + count = 1
     182 + }
     183 + offset = 0;
     184 + }
     185 + _ => {
     186 + opcode >>= 1;
     187 + count = (code & 0x1f) as u16;
     188 + offset = 32;
     189 + }
     190 + }
     191 + 
     192 + if offset != 0 {
     193 + isfillormix = (opcode == 2) || (opcode == 7);
     194 + if count == 0 {
     195 + if isfillormix {
     196 + count = input_cursor.read_u8()? as u16 + 1;
     197 + } else {
     198 + count = input_cursor.read_u8()? as u16 + offset;
     199 + }
     200 + } else if isfillormix {
     201 + count <<= 3;
     202 + }
     203 + }
     204 + 
     205 + match opcode {
     206 + 0 => {
     207 + if lastopcode == opcode && !(x == width && prevline == None) {
     208 + insertmix = true;
     209 + }
     210 + },
     211 + 8 => {
     212 + colour1 = input_cursor.read_u16::<LittleEndian>()?;
     213 + colour2 = input_cursor.read_u16::<LittleEndian>()?;
     214 + },
     215 + 3 => {
     216 + colour2 = input_cursor.read_u16::<LittleEndian>()?;
     217 + },
     218 + 6 | 7 => {
     219 + mix = input_cursor.read_u16::<LittleEndian>()?;
     220 + opcode -= 5;
     221 + }
     222 + 9 => {
     223 + mask = 0x03;
     224 + opcode = 0x02;
     225 + fom_mask = 3;
     226 + },
     227 + 0xa => {
     228 + mask = 0x05;
     229 + opcode = 0x02;
     230 + fom_mask = 5;
     231 + }
     232 + _ => ()
     233 + }
     234 + lastopcode = opcode;
     235 + mixmask = 0;
     236 + 
     237 + while count > 0 {
     238 + if x >= width {
     239 + if height <= 0 {
     240 + Err(());
     241 + }
     242 + x = 0;
     243 + height -= 1;
     244 + prevline = line;
     245 + line = Some(height * width);
     246 + }
     247 + 
     248 + match opcode {
     249 + 0 => {
     250 + if insertmix {
     251 + if let Some(e) = prevline {
     252 + output[line.unwrap() + x] = output[e + x] ^ mix;
     253 + }
     254 + else {
     255 + output[line.unwrap() + x] = mix;
     256 + }
     257 + insertmix = false;
     258 + count -= 1;
     259 + x += 1;
     260 + }
     261 + 
     262 + if let Some(e) = prevline {
     263 + repeat!(output[line.unwrap() + x] = output[e + x], count, x, width);
     264 + }
     265 + else {
     266 + repeat!(output[line.unwrap() + x] = 0, count, x, width);
     267 + }
     268 + },
     269 + 1 => {
     270 + if let Some(e) = prevline {
     271 + repeat!(output[line.unwrap() + x] = output[e + x] ^ mix, count, x, width);
     272 + }
     273 + else {
     274 + repeat!(output[line.unwrap() + x] = mix, count, x, width);
     275 + }
     276 + },
     277 + 2 => {
     278 + if let Some(e) = prevline {
     279 + repeat!({
     280 + mixmask <<= 1;
     281 + if mixmask == 0 {
     282 + mask = if fom_mask != 0 { fom_mask } else { input_cursor.read_u8()? };
     283 + mixmask = 1;
     284 + }
     285 + if (mask & mixmask) != 0 {
     286 + output[line.unwrap() + x] = output[e + x] ^ mix;
     287 + }
     288 + else {
     289 + output[line.unwrap() + x] = output[e + x];
     290 + }
     291 + }, count, x, width);
     292 + }
     293 + else {
     294 + repeat!({
     295 + mixmask <<= 1;
     296 + if mixmask == 0 {
     297 + mask = if fom_mask != 0 { fom_mask } else { input_cursor.read_u8()? };
     298 + mixmask = 1;
     299 + }
     300 + if (mask & mixmask) != 0 {
     301 + output[line.unwrap() + x] = mix;
     302 + }
     303 + else {
     304 + output[line.unwrap() + x] = 0;
     305 + }
     306 + }, count, x, width);
     307 + }
     308 + },
     309 + 3 => {
     310 + repeat!(output[line.unwrap() + x] = colour2, count, x, width);
     311 + },
     312 + 4 => {
     313 + repeat!(output[line.unwrap() + x] = input_cursor.read_u16::<LittleEndian>()?, count, x, width);
     314 + },
     315 + 8 => {
     316 + repeat!({
     317 + if bicolour {
     318 + output[line.unwrap() + x] = colour2;
     319 + bicolour = false;
     320 + } else {
     321 + output[line.unwrap() + x] = colour1;
     322 + bicolour = true;
     323 + count += 1;
     324 + };
     325 + }, count, x, width);
     326 + },
     327 + 0xd => {
     328 + repeat!(output[line.unwrap() + x] = 0xffff, count, x, width);
     329 + },
     330 + 0xe => {
     331 + repeat!(output[line.unwrap() + x] = 0, count, x, width);
     332 + }
     333 + _ => panic!("opcode")
     334 + }
     335 + }
     336 + }
     337 + 
     338 + Ok(())
     339 +}
     340 + 
     341 + 
     342 +pub fn rgb565torgb32(input: &[u16], width: usize, height: usize) -> Vec<u8> {
     343 + let mut result_32_bpp = vec![0 as u8; width as usize * height as usize * 4];
     344 + for i in 0..height {
     345 + for j in 0..width {
     346 + let index = (i * width + j) as usize;
     347 + let v = input[index];
     348 + result_32_bpp[index * 4 + 3] = 0xff;
     349 + result_32_bpp[index * 4 + 2] = (((((v >> 11) & 0x1f) * 527) + 23) >> 6) as u8;
     350 + result_32_bpp[index * 4 + 1] = (((((v >> 5) & 0x3f) * 259) + 33) >> 6) as u8;
     351 + result_32_bpp[index * 4] = ((((v & 0x1f) * 527) + 23) >> 6) as u8;
     352 + }
     353 + }
     354 + result_32_bpp
     355 +}
     356 + 
     357 +fn bitmap_decompress( input: &mut Vec<u8>, width: i16, height: i16, output: &mut Vec<u8>, bpp: usize) -> bool {
     358 + let mut rv = false;
     359 + match bpp {
     360 + 2 => rv = rle_16_decompress(input, width, height, output),
     361 + 4 => rv = rle_32_decompress(input, width, height, output),
     362 + _ => (),
     363 + }
     364 + rv
     365 +}
     366 + 
     367 + 
     368 +// *INDENT-ON*
     369 +#[pyfunction]
     370 +#[pyo3(name = "bitmap_decompress")]
     371 +fn bitmap_decompress_wrapper(py: Python<'_>, output: PyBuffer<u8>, width: usize, height: usize, input: PyBuffer<u8>, bitsperpixel: usize, bpp: usize, is_compressed: usize) -> PyResult<&PyByteArray> {
     372 + let mut decomp_size = 0usize;
     373 + let mut decomp_buffer;
     374 + 
     375 + if is_compressed != 0 {
     376 + decomp_size = width * height * bpp;
     377 + decomp_buffer = vec![0; decomp_size];
     378 + 
     379 + if !bitmap_decompress(&mut input.to_vec(py).unwrap(), width, height, &mut decomp_buffer, bpp) {
     380 + return Err(PyTypeError::new_err("Decompression Error"));
     381 + }
     382 + } else {
     383 + decomp_size = input.len_bytes();
     384 + decomp_buffer = input.to_vec(py).unwrap();
     385 + }
     386 + 
     387 + let mut output_buffer = output.to_vec(py).unwrap();
     388 + 
     389 + if bitsperpixel == 16 {
     390 + rgb565torgb32(decomp_buffer, width, height);
     391 + }
     392 + 
     393 + let output_as_bytes = PyByteArray::new(py, &output_buffer);
     394 + return Ok(output_as_bytes);
     395 +}
     396 + 
     397 + 
     398 +#[pymodule]
     399 +fn rle(py: Python<'_>, m: &PyModule) -> PyResult<()> {
     400 + m.add_function(wrap_pyfunction!(bitmap_decompress_wrapper, m)?)?;
     401 + //m.add_function(wrap_pyfunction!(mask_rgbx_wrapper, m)?)?;
     402 + //m.add_function(wrap_pyfunction!(decode_rre_wrapper, m)?)?;
     403 + Ok(())
     404 +}
  • ■ ■ ■ ■ ■ ■
    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  -)
  • ■ ■ ■ ■ ■
    setup.py
    1 1  from setuptools import setup, find_packages
    2  -from distutils.core import setup, Extension
    3 2  import re
    4  -import platform
     3 +from setuptools_rust import Binding, RustExtension
    5 4   
    6 5  VERSIONFILE="aardwolf/_version.py"
    7 6  verstrline = open(VERSIONFILE, "rt").read()
    skipped 3 lines
    11 10   verstr = mo.group(1)
    12 11  else:
    13 12   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 13   
    22 14  setup(
    23 15   # Application name:
    skipped 24 lines
    48 40   # long_description=open("README.txt").read(),
    49 41   python_requires='>=3.7',
    50 42  
    51  - ext_modules = [rle_module],
    52  - 
     43 + rust_extensions=[RustExtension("rle", 'aardwolf/utils/rle/Cargo.toml', binding=Binding.PyO3)],
    53 44   
    54 45   install_requires=[
    55 46   'unicrypto>=0.0.9',
    56  - 'asyauth>=0.0.2',
    57  - 'asysocks>=0.2.1',
     47 + 'asyauth>=0.0.3',
     48 + 'asysocks>=0.2.2',
    58 49   'minikerberos>=0.3.1',
    59 50   'tqdm',
    60 51   'colorama',
    skipped 19 lines
Please wait...
Page is in error, reload to recover