author | mickeyl <mickeyl> | 2003-08-10 15:17:24 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2003-08-10 15:17:24 (UTC) |
commit | 1fb2f4ef9788b51c67b9c0f89ac3c3ce85e45e8f (patch) (side-by-side diff) | |
tree | 73b54db5d3aa3e40f4159079c14c8fca90a76c1e /noncore/net/opierdesktop/bitmap.cpp | |
parent | df6337abb65463b466435a526bf62108e72a60f7 (diff) | |
download | opie-1fb2f4ef9788b51c67b9c0f89ac3c3ce85e45e8f.zip opie-1fb2f4ef9788b51c67b9c0f89ac3c3ce85e45e8f.tar.gz opie-1fb2f4ef9788b51c67b9c0f89ac3c3ce85e45e8f.tar.bz2 |
initial import of qtrdesktop - not yet opiefied but working
Diffstat (limited to 'noncore/net/opierdesktop/bitmap.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | noncore/net/opierdesktop/bitmap.cpp | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/noncore/net/opierdesktop/bitmap.cpp b/noncore/net/opierdesktop/bitmap.cpp new file mode 100644 index 0000000..378623f --- a/dev/null +++ b/noncore/net/opierdesktop/bitmap.cpp @@ -0,0 +1,282 @@ +/* + rdesktop: A Remote Desktop Protocol client. + Bitmap decompression routines + Copyright (C) Matthew Chapman 1999-2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "rdesktop.h" + +#define CVAL(p) (*(p++)) + +static uint32 +cvalx(unsigned char **input, int Bpp) +{ + uint32 rv = 0; + memcpy(&rv, *input, Bpp); + *input += Bpp; + return rv; +} + +static void +setli(unsigned char *input, int offset, uint32 value, int Bpp) +{ + input += offset * Bpp; + memcpy(input, &value, Bpp); +} + +static uint32 +getli(unsigned char *input, int offset, int Bpp) +{ + uint32 rv = 0; + input += offset * Bpp; + memcpy(&rv, input, Bpp); + return rv; +} + +#define UNROLL8(exp) { exp exp exp exp exp exp exp exp } + +#define REPEAT(statement) \ +{ \ + while((count & ~0x7) && ((x+8) < width)) \ + UNROLL8( statement; count--; x++; ); \ + \ + while((count > 0) && (x < width)) { statement; count--; x++; } \ +} + +#define MASK_UPDATE() \ +{ \ + mixmask <<= 1; \ + if (mixmask == 0) \ + { \ + mask = fom_mask ? fom_mask : CVAL(input); \ + mixmask = 1; \ + } \ +} + +BOOL +bitmap_decompress(unsigned char *output, int width, int height, unsigned char *input, int size, + int Bpp) +{ + unsigned char *end = input + size; + unsigned char *prevline = NULL, *line = NULL; + int opcode, count, offset, isfillormix, x = width; + int lastopcode = -1, insertmix = False, bicolour = False; + uint8 code; + uint32 colour1 = 0, colour2 = 0; + uint8 mixmask, mask = 0; + uint32 mix = 0xffffffff; + int fom_mask = 0; + + while (input < end) + { + fom_mask = 0; + code = CVAL(input); + opcode = code >> 4; + + /* Handle different opcode forms */ + switch (opcode) + { + case 0xc: + case 0xd: + case 0xe: + opcode -= 6; + count = code & 0xf; + offset = 16; + break; + + case 0xf: + opcode = code & 0xf; + if (opcode < 9) + { + count = CVAL(input); + count |= CVAL(input) << 8; + } + else + { + count = (opcode < 0xb) ? 8 : 1; + } + offset = 0; + break; + + default: + opcode >>= 1; + count = code & 0x1f; + offset = 32; + break; + } + + /* Handle strange cases for counts */ + if (offset != 0) + { + isfillormix = ((opcode == 2) || (opcode == 7)); + + if (count == 0) + { + if (isfillormix) + count = CVAL(input) + 1; + else + count = CVAL(input) + offset; + } + else if (isfillormix) + { + count <<= 3; + } + } + + /* Read preliminary data */ + switch (opcode) + { + case 0: /* Fill */ + if ((lastopcode == opcode) && !((x == width) && (prevline == NULL))) + insertmix = True; + break; + case 8: /* Bicolour */ + colour1 = cvalx(&input, Bpp); + case 3: /* Colour */ + colour2 = cvalx(&input, Bpp); + break; + case 6: /* SetMix/Mix */ + case 7: /* SetMix/FillOrMix */ + mix = cvalx(&input, Bpp); + opcode -= 5; + break; + case 9: /* FillOrMix_1 */ + mask = 0x03; + opcode = 0x02; + fom_mask = 3; + break; + case 0x0a: /* FillOrMix_2 */ + mask = 0x05; + opcode = 0x02; + fom_mask = 5; + break; + + } + + lastopcode = opcode; + mixmask = 0; + + /* Output body */ + while (count > 0) + { + if (x >= width) + { + if (height <= 0) + return False; + + x = 0; + height--; + + prevline = line; + line = output + height * width * Bpp; + } + + switch (opcode) + { + case 0: /* Fill */ + if (insertmix) + { + if (prevline == NULL) + setli(line, x, mix, Bpp); + else + setli(line, x, + getli(prevline, x, Bpp) ^ mix, Bpp); + + insertmix = False; + count--; + x++; + } + + if (prevline == NULL) + { + REPEAT(setli(line, x, 0, Bpp))} + else + { + REPEAT(setli + (line, x, getli(prevline, x, Bpp), Bpp)); + } + break; + + case 1: /* Mix */ + if (prevline == NULL) + { + REPEAT(setli(line, x, mix, Bpp)); + } + else + { + REPEAT(setli + (line, x, getli(prevline, x, Bpp) ^ mix, + Bpp)); + } + break; + + case 2: /* Fill or Mix */ + if (prevline == NULL) + { + REPEAT(MASK_UPDATE(); + if (mask & mixmask) setli(line, x, mix, Bpp); + else + setli(line, x, 0, Bpp);); + } + else + { + REPEAT(MASK_UPDATE(); + if (mask & mixmask) + setli(line, x, getli(prevline, x, Bpp) ^ mix, + Bpp); + else + setli(line, x, getli(prevline, x, Bpp), + Bpp);); + } + break; + + case 3: /* Colour */ + REPEAT(setli(line, x, colour2, Bpp)); + break; + + case 4: /* Copy */ + REPEAT(setli(line, x, cvalx(&input, Bpp), Bpp)); + break; + + case 8: /* Bicolour */ + REPEAT(if (bicolour) + { + setli(line, x, colour2, Bpp); bicolour = False;} + else + { + setli(line, x, colour1, Bpp); bicolour = True; + count++;} + ); + break; + + case 0xd: /* White */ + REPEAT(setli(line, x, 0xffffffff, Bpp)); + break; + + case 0xe: /* Black */ + REPEAT(setli(line, x, 0, Bpp)); + break; + + default: + unimpl("bitmap opcode 0x%x\n", opcode); + return False; + } + } + } + + return True; +} |