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:
Jay Sorg 2003-02-07 23:43:37 +00:00
parent d3b577525c
commit c50d176caf
4 changed files with 62 additions and 257 deletions

288
bitmap.c
View File

@ -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;
}

View File

@ -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);

View File

@ -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
View File

@ -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);
}