18 |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
19 |
*/ |
*/ |
20 |
|
|
21 |
/* three seperate function for speed when decompressing the bitmaps */ |
/* three seperate function for speed when decompressing the bitmaps |
22 |
/* when modifing one function make the change in the others */ |
when modifing one function make the change in the others |
23 |
/* comment out #define BITMAP_SPEED_OVER_SIZE below for one slower function */ |
jay.sorg@gmail.com */ |
|
/* j@american-data.com */ |
|
|
|
|
|
#define BITMAP_SPEED_OVER_SIZE |
|
24 |
|
|
25 |
/* indent is confused by this file */ |
/* indent is confused by this file */ |
26 |
/* *INDENT-OFF* */ |
/* *INDENT-OFF* */ |
63 |
} \ |
} \ |
64 |
} |
} |
65 |
|
|
|
#ifdef BITMAP_SPEED_OVER_SIZE |
|
|
|
|
66 |
/* 1 byte bitmap decompress */ |
/* 1 byte bitmap decompress */ |
67 |
static BOOL |
static BOOL |
68 |
bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size) |
bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size) |
746 |
return True; |
return True; |
747 |
} |
} |
748 |
|
|
|
#else |
|
|
|
|
|
static uint32 |
|
|
cvalx(uint8 **input, int Bpp) |
|
|
{ |
|
|
uint32 rv = 0; |
|
|
memcpy(&rv, *input, Bpp); |
|
|
*input += Bpp; |
|
|
return rv; |
|
|
} |
|
|
|
|
|
static void |
|
|
setli(uint8 *input, int offset, uint32 value, int Bpp) |
|
|
{ |
|
|
input += offset * Bpp; |
|
|
memcpy(input, &value, Bpp); |
|
|
} |
|
|
|
|
|
static uint32 |
|
|
getli(uint8 *input, int offset, int Bpp) |
|
|
{ |
|
|
uint32 rv = 0; |
|
|
input += offset * Bpp; |
|
|
memcpy(&rv, input, Bpp); |
|
|
return rv; |
|
|
} |
|
|
|
|
|
static BOOL |
|
|
bitmap_decompressx(uint8 *output, int width, int height, uint8 *input, int size, int Bpp) |
|
|
{ |
|
|
uint8 *end = input + size; |
|
|
uint8 *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; |
|
|
} |
|
|
|
|
|
#endif |
|
|
|
|
749 |
/* main decompress function */ |
/* main decompress function */ |
750 |
BOOL |
BOOL |
751 |
bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp) |
bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp) |
752 |
{ |
{ |
|
#ifdef BITMAP_SPEED_OVER_SIZE |
|
753 |
BOOL rv = False; |
BOOL rv = False; |
754 |
|
|
755 |
switch (Bpp) |
switch (Bpp) |
756 |
{ |
{ |
757 |
case 1: |
case 1: |
764 |
rv = bitmap_decompress3(output, width, height, input, size); |
rv = bitmap_decompress3(output, width, height, input, size); |
765 |
break; |
break; |
766 |
} |
} |
|
#else |
|
|
BOOL rv; |
|
|
rv = bitmap_decompressx(output, width, height, input, size, Bpp); |
|
|
#endif |
|
767 |
return rv; |
return rv; |
768 |
} |
} |
769 |
|
|