one bitmap decomp function to handle all colour depths
git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@313 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
parent
d3b577525c
commit
c50d176caf
288
bitmap.c
288
bitmap.c
@ -21,7 +21,28 @@
|
||||
#include "rdesktop.h"
|
||||
|
||||
#define CVAL(p) (*(p++))
|
||||
#define CVAL16(p) (*(((uint16*)p)++))
|
||||
|
||||
uint32 cvalx(unsigned char **input, int Bpp)
|
||||
{
|
||||
uint32 rv = 0;
|
||||
memcpy(&rv, *input, Bpp);
|
||||
*input += Bpp;
|
||||
return rv;
|
||||
}
|
||||
|
||||
void setli(unsigned char * input, int offset, uint32 value, int Bpp)
|
||||
{
|
||||
input += offset * Bpp;
|
||||
memcpy(input, &value, Bpp);
|
||||
}
|
||||
|
||||
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 }
|
||||
|
||||
@ -44,14 +65,16 @@
|
||||
}
|
||||
|
||||
BOOL
|
||||
bitmap_decompress8(unsigned char *output, int width, int height, unsigned char *input, int size)
|
||||
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, colour1 = 0, colour2 = 0;
|
||||
uint8 mixmask, mask = 0, mix = 0xff;
|
||||
uint8 code;
|
||||
uint32 colour1 = 0, colour2 = 0;
|
||||
uint8 mixmask, mask = 0;
|
||||
uint32 mix = 0xffffffff;
|
||||
int fom_mask = 0;
|
||||
|
||||
while (input < end)
|
||||
@ -118,13 +141,13 @@ bitmap_decompress8(unsigned char *output, int width, int height, unsigned char *
|
||||
insertmix = True;
|
||||
break;
|
||||
case 8: /* Bicolour */
|
||||
colour1 = CVAL(input);
|
||||
colour1 = cvalx(&input, Bpp);
|
||||
case 3: /* Colour */
|
||||
colour2 = CVAL(input);
|
||||
colour2 = cvalx(&input, Bpp);
|
||||
break;
|
||||
case 6: /* SetMix/Mix */
|
||||
case 7: /* SetMix/FillOrMix */
|
||||
mix = CVAL(input);
|
||||
mix = cvalx(&input, Bpp);
|
||||
opcode -= 5;
|
||||
break;
|
||||
case 9: /* FillOrMix_1 */
|
||||
@ -155,7 +178,7 @@ bitmap_decompress8(unsigned char *output, int width, int height, unsigned char *
|
||||
height--;
|
||||
|
||||
prevline = line;
|
||||
line = output + height * width;
|
||||
line = output + height * width * Bpp;
|
||||
}
|
||||
|
||||
switch (opcode)
|
||||
@ -164,9 +187,9 @@ bitmap_decompress8(unsigned char *output, int width, int height, unsigned char *
|
||||
if (insertmix)
|
||||
{
|
||||
if (prevline == NULL)
|
||||
line[x] = mix;
|
||||
setli(line, x, mix, Bpp);
|
||||
else
|
||||
line[x] = prevline[x] ^ mix;
|
||||
setli(line, x, getli(prevline, x, Bpp) ^ mix, Bpp);
|
||||
|
||||
insertmix = False;
|
||||
count--;
|
||||
@ -175,22 +198,22 @@ bitmap_decompress8(unsigned char *output, int width, int height, unsigned char *
|
||||
|
||||
if (prevline == NULL)
|
||||
{
|
||||
REPEAT(line[x] = 0);
|
||||
REPEAT(setli(line, x, 0, Bpp))
|
||||
}
|
||||
else
|
||||
{
|
||||
REPEAT(line[x] = prevline[x]);
|
||||
REPEAT(setli(line, x, getli(prevline, x, Bpp), Bpp));
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: /* Mix */
|
||||
if (prevline == NULL)
|
||||
{
|
||||
REPEAT(line[x] = mix);
|
||||
REPEAT(setli(line, x, mix, Bpp));
|
||||
}
|
||||
else
|
||||
{
|
||||
REPEAT(line[x] = prevline[x] ^ mix);
|
||||
REPEAT(setli(line, x, getli(prevline, x, Bpp) ^ mix, Bpp));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -198,44 +221,44 @@ bitmap_decompress8(unsigned char *output, int width, int height, unsigned char *
|
||||
if (prevline == NULL)
|
||||
{
|
||||
REPEAT(MASK_UPDATE();
|
||||
if (mask & mixmask) line[x] = mix;
|
||||
if (mask & mixmask) setli(line, x, mix, Bpp);
|
||||
else
|
||||
line[x] = 0;);
|
||||
setli(line, x, 0, Bpp););
|
||||
}
|
||||
else
|
||||
{
|
||||
REPEAT(MASK_UPDATE();
|
||||
if (mask & mixmask)
|
||||
line[x] = prevline[x] ^ mix;
|
||||
setli(line, x, getli(prevline, x, Bpp) ^ mix, Bpp);
|
||||
else
|
||||
line[x] = prevline[x];);
|
||||
setli(line, x, getli(prevline, x, Bpp), Bpp););
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: /* Colour */
|
||||
REPEAT(line[x] = colour2);
|
||||
REPEAT(setli(line, x, colour2, Bpp));
|
||||
break;
|
||||
|
||||
case 4: /* Copy */
|
||||
REPEAT(line[x] = CVAL(input));
|
||||
REPEAT(setli(line, x, cvalx(&input, Bpp), Bpp));
|
||||
break;
|
||||
|
||||
case 8: /* Bicolour */
|
||||
REPEAT(if (bicolour)
|
||||
{
|
||||
line[x] = colour2; bicolour = False;}
|
||||
setli(line, x, colour2, Bpp); bicolour = False;}
|
||||
else
|
||||
{
|
||||
line[x] = colour1; bicolour = True; count++;}
|
||||
setli(line, x, colour1, Bpp); bicolour = True; count++;}
|
||||
);
|
||||
break;
|
||||
|
||||
case 0xd: /* White */
|
||||
REPEAT(line[x] = 0xff);
|
||||
REPEAT(setli(line, x, 0xffffffff, Bpp));
|
||||
break;
|
||||
|
||||
case 0xe: /* Black */
|
||||
REPEAT(line[x] = 0x00);
|
||||
REPEAT(setli(line, x, 0, Bpp));
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -248,220 +271,3 @@ bitmap_decompress8(unsigned char *output, int width, int height, unsigned char *
|
||||
return True;
|
||||
}
|
||||
|
||||
BOOL
|
||||
bitmap_decompress16(unsigned char *output, int width, int height, unsigned char *input, int size)
|
||||
{
|
||||
unsigned char *end = input + size;
|
||||
uint16 *prevline = NULL, *line = NULL;
|
||||
int opcode, count, offset, isfillormix, x = width;
|
||||
int lastopcode = -1, insertmix = False, bicolour = False;
|
||||
uint8 code;
|
||||
uint16 colour1 = 0, colour2 = 0;
|
||||
uint8 mixmask, mask = 0;
|
||||
uint16 mix = 0xffff;
|
||||
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 < 0xd) ? 8 : 1; // was 0xb in 8 bit
|
||||
}
|
||||
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 = CVAL16(input);
|
||||
case 3: /* Colour */
|
||||
colour2 = CVAL16(input);
|
||||
break;
|
||||
case 6: /* SetMix/Mix */
|
||||
case 7: /* SetMix/FillOrMix */
|
||||
mix = CVAL16(input);
|
||||
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 = (uint16*)output + height * width;
|
||||
}
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case 0: /* Fill */
|
||||
if (insertmix)
|
||||
{
|
||||
if (prevline == NULL)
|
||||
line[x] = mix;
|
||||
else
|
||||
line[x] = prevline[x] ^ mix;
|
||||
|
||||
insertmix = False;
|
||||
count--;
|
||||
x++;
|
||||
}
|
||||
|
||||
if (prevline == NULL)
|
||||
{
|
||||
REPEAT(line[x] = 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
REPEAT(line[x] = prevline[x]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: /* Mix */
|
||||
if (prevline == NULL)
|
||||
{
|
||||
REPEAT(line[x] = mix);
|
||||
}
|
||||
else
|
||||
{
|
||||
REPEAT(line[x] = prevline[x] ^ mix);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* Fill or Mix */
|
||||
if (prevline == NULL)
|
||||
{
|
||||
REPEAT(MASK_UPDATE();
|
||||
if (mask & mixmask) line[x] = mix;
|
||||
else
|
||||
line[x] = 0;);
|
||||
}
|
||||
else
|
||||
{
|
||||
REPEAT(MASK_UPDATE();
|
||||
if (mask & mixmask)
|
||||
line[x] = prevline[x] ^ mix;
|
||||
else
|
||||
line[x] = prevline[x];);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: /* Colour */
|
||||
REPEAT(line[x] = colour2);
|
||||
break;
|
||||
|
||||
case 4: /* Copy */
|
||||
REPEAT(line[x] = CVAL16(input));
|
||||
break;
|
||||
|
||||
case 8: /* Bicolour */
|
||||
REPEAT(if (bicolour)
|
||||
{
|
||||
line[x] = colour2; bicolour = False;}
|
||||
else
|
||||
{
|
||||
line[x] = colour1; bicolour = True; count++;}
|
||||
);
|
||||
break;
|
||||
|
||||
case 0xd: /* White */
|
||||
REPEAT(line[x] = 0xffff);
|
||||
break;
|
||||
|
||||
case 0xe: /* Black */
|
||||
REPEAT(line[x] = 0x00);
|
||||
break;
|
||||
|
||||
default:
|
||||
unimpl("bitmap opcode 0x%x\n", opcode);
|
||||
return False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
BOOL
|
||||
bitmap_decompress(unsigned char *output, int width, int height, unsigned char *input, int size, int bpp)
|
||||
{
|
||||
if (bpp == 8)
|
||||
return bitmap_decompress8(output, width, height, input, size);
|
||||
else if (bpp == 16)
|
||||
return bitmap_decompress16(output, width, height, input, size);
|
||||
else
|
||||
return False;
|
||||
}
|
||||
|
18
orders.c
18
orders.c
@ -641,7 +641,7 @@ process_raw_bmpcache(STREAM s)
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
uint16 cache_idx, bufsize;
|
||||
uint8 cache_id, width, height, bpp;
|
||||
uint8 cache_id, width, height, bpp, Bpp;
|
||||
uint8 *data, *inverted;
|
||||
int y;
|
||||
|
||||
@ -650,17 +650,16 @@ process_raw_bmpcache(STREAM s)
|
||||
in_uint8(s, width);
|
||||
in_uint8(s, height);
|
||||
in_uint8(s, bpp);
|
||||
Bpp = (bpp + 7) / 8;
|
||||
in_uint16_le(s, bufsize);
|
||||
in_uint16_le(s, cache_idx);
|
||||
in_uint8p(s, data, bufsize);
|
||||
if (bpp != 8) /* todo */
|
||||
return;
|
||||
|
||||
DEBUG(("RAW_BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width, height, cache_id, cache_idx));
|
||||
inverted = xmalloc(width * height);
|
||||
inverted = xmalloc(width * height * Bpp);
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
memcpy(&inverted[(height - y - 1) * width], &data[y * width], width);
|
||||
memcpy(&inverted[(height - y - 1) * (width * Bpp)], &data[y * (width * Bpp)], width * Bpp);
|
||||
}
|
||||
|
||||
bitmap = ui_create_bitmap(width, height, inverted);
|
||||
@ -674,7 +673,7 @@ process_bmpcache(STREAM s)
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
uint16 cache_idx, size;
|
||||
uint8 cache_id, width, height, bpp;
|
||||
uint8 cache_id, width, height, bpp, Bpp;
|
||||
uint8 *data, *bmpdata;
|
||||
|
||||
in_uint8(s, cache_id);
|
||||
@ -682,20 +681,19 @@ process_bmpcache(STREAM s)
|
||||
in_uint8(s, width);
|
||||
in_uint8(s, height);
|
||||
in_uint8(s, bpp);
|
||||
Bpp = (bpp + 7) / 8;
|
||||
in_uint8s(s, 2); /* bufsize */
|
||||
in_uint16_le(s, cache_idx);
|
||||
in_uint8s(s, 2); /* pad */
|
||||
in_uint16_le(s, size);
|
||||
in_uint8s(s, 4); /* row_size, final_size */
|
||||
in_uint8p(s, data, size);
|
||||
if (bpp != 8) /* todo */
|
||||
return;
|
||||
|
||||
DEBUG(("BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width, height, cache_id, cache_idx));
|
||||
|
||||
bmpdata = xmalloc(width * height);
|
||||
bmpdata = xmalloc(width * height * Bpp);
|
||||
|
||||
if (bitmap_decompress(bmpdata, width, height, data, size, bpp))
|
||||
if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
|
||||
{
|
||||
bitmap = ui_create_bitmap(width, height, bmpdata);
|
||||
cache_put_bitmap(cache_id, cache_idx, bitmap);
|
||||
|
2
proto.h
2
proto.h
@ -1,6 +1,6 @@
|
||||
/* bitmap.c */
|
||||
BOOL bitmap_decompress(unsigned char *output, int width, int height, unsigned char *input,
|
||||
int size, int bpp);
|
||||
int size, int Bpp);
|
||||
/* cache.c */
|
||||
HBITMAP cache_get_bitmap(uint8 cache_id, uint16 cache_idx);
|
||||
void cache_put_bitmap(uint8 cache_id, uint16 cache_idx, HBITMAP bitmap);
|
||||
|
11
rdp.c
11
rdp.c
@ -552,7 +552,7 @@ process_bitmap_updates(STREAM s)
|
||||
{
|
||||
uint16 num_updates;
|
||||
uint16 left, top, right, bottom, width, height;
|
||||
uint16 cx, cy, bpp, compress, bufsize, size;
|
||||
uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
|
||||
uint8 *data, *bmpdata;
|
||||
int i;
|
||||
|
||||
@ -567,6 +567,7 @@ process_bitmap_updates(STREAM s)
|
||||
in_uint16_le(s, width);
|
||||
in_uint16_le(s, height);
|
||||
in_uint16_le(s, bpp);
|
||||
Bpp = (bpp + 7) / 8;
|
||||
in_uint16_le(s, compress);
|
||||
in_uint16_le(s, bufsize);
|
||||
|
||||
@ -579,10 +580,10 @@ process_bitmap_updates(STREAM s)
|
||||
if (!compress)
|
||||
{
|
||||
int y;
|
||||
bmpdata = xmalloc(width * height * (bpp / 8));
|
||||
bmpdata = xmalloc(width * height * Bpp);
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
in_uint8a(s, &bmpdata[(height - y - 1) * (width * (bpp / 8))], width * (bpp / 8));
|
||||
in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)], width * Bpp);
|
||||
}
|
||||
ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
|
||||
xfree(bmpdata);
|
||||
@ -593,8 +594,8 @@ process_bitmap_updates(STREAM s)
|
||||
in_uint16_le(s, size);
|
||||
in_uint8s(s, 4); /* line_size, final_size */
|
||||
in_uint8p(s, data, size);
|
||||
bmpdata = xmalloc(width * height * (bpp / 8));
|
||||
if (bitmap_decompress(bmpdata, width, height, data, size, bpp))
|
||||
bmpdata = xmalloc(width * height * Bpp);
|
||||
if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
|
||||
{
|
||||
ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user