Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions encode_dxa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class DxaEncoder {
void m13blockDelta(byte *frame, int x, int y, int x2, int y2, DiffStruct &diff);
bool m13motionVector(byte *frame, int x, int y, int w, int h, int &mx, int &my);
int m13countColors(byte *block, byte *pixels, unsigned long &code, int &codeSize);
uLong m12encode(byte *frame, byte *outbuf);
uLong m13encode(byte *frame, byte *outbuf);

public:
Expand Down Expand Up @@ -196,6 +197,57 @@ void DxaEncoder::writeFrame(byte *frame, byte *palette) {
delete[] outbuf2;
delete[] xorbuf;

break;
}
case 12:
{
uLong outsize1 = _width * _workheight;
uLong outsize2 = outsize1;
uLong outsize3 = outsize1*2;
uLong outsize4 = outsize1;
uLong outsize;
uint8 *outbuf;
uint8 *outbuf1 = new uint8[outsize1];
uint8 *outbuf2 = new uint8[outsize2];
uint8 *outbuf3 = new uint8[outsize3];
uint8 *outbuf4 = new uint8[outsize4];
uint8 *xorbuf = new uint8[_width * _workheight];

for (int i = 0; i < _width * _workheight; i++)
xorbuf[i] = _prevframe[i] ^ frame[i];

compress2(outbuf1, &outsize1, xorbuf, _width * _workheight, 9);
compress2(outbuf2, &outsize2, frame, _width * _workheight, 9);
if (outsize1 < outsize2) {
compType = 3;
outsize = outsize1;
outbuf = outbuf1;
} else {
compType = 2;
outsize = outsize2;
outbuf = outbuf2;
}

outsize3 = m12encode(frame, outbuf3);

compress2(outbuf4, &outsize4, outbuf3, outsize3, 9);

if (outsize4 < outsize) {
compType = 12;
outsize = outsize4;
outbuf = outbuf4;
}

_dxa.writeByte(compType);
_dxa.writeUint32BE(outsize);
_dxa.write(outbuf, outsize);

delete[] outbuf1;
delete[] outbuf2;
delete[] outbuf3;
delete[] outbuf4;
delete[] xorbuf;

break;
}
case 13:
Expand Down Expand Up @@ -382,6 +434,86 @@ void DxaEncoder::grabBlock(byte *frame, int x, int y, int blockw, int blockh, by
}
}

uLong DxaEncoder::m12encode(byte *frame, byte *outbuf) {
byte *outb = outbuf;
byte color;
int mx, my;
DiffStruct diff;

for (int by = 0; by < _workheight; by += BLOCKH) {
for (int bx = 0; bx < _width; bx += BLOCKW) {
if (m13blocksAreEqual(frame, bx, by, bx, by, BLOCKW, BLOCKH)) {
*outb++ = 0;
continue;
}

if (m13blockIsSolidColor(frame, bx, by, BLOCKW, BLOCKH, color)) {
*outb++ = 2;
*outb++ = color;
continue;
}

if (m13motionVector(frame, bx, by, BLOCKW, BLOCKH, mx, my)) {
byte mbyte = 0;
if (mx < 0) mbyte |= 0x80;
mbyte |= (abs(mx) & 7) << 4;
if (my < 0) mbyte |= 0x08;
mbyte |= abs(my) & 7;
*outb++ = 4;
*outb++ = mbyte;
continue;
}

m13blockDelta(frame, bx, by, bx, by, diff);

if (diff.count >= 14) {
// in this case we store all 16 pixels
*outb++ = 3;
byte *b2 = (byte*)frame + bx + by * _width;
for (int yc = 0; yc < BLOCKH; yc++) {
memcpy(outb, b2, BLOCKW);
b2 += _width;
outb += BLOCKW;
}
continue;
} else {
static const struct { uint16 mask; uint8 sh1, sh2; } maskTbl[6] = {
{0xFF00, 0, 0},
{0x0FF0, 8, 0},
{0x00FF, 8, 8},
{0x0F0F, 8, 4},
{0xF0F0, 4, 0},
{0xF00F, 4, 4}
};

bool smallMask = false;

// here we check if the difference bitmap can be stored in only one byte
for (int m = 0; m < 6; m++) {
if ((diff.map & maskTbl[m].mask) == 0) {
smallMask = true;
*outb++ = 10 + m;
*outb++ = ((diff.map >> maskTbl[m].sh1) & 0xF0) | ((diff.map >> maskTbl[m].sh2) & 0x0F);
break;
}
}

if (!smallMask) {
*outb++ = 1;
WRITE_BE_UINT16(outb, diff.map);
outb += 2;
}

memcpy(outb, diff.pixels, diff.count);
outb += diff.count;
continue;
}
}
}

return outb - outbuf;
}

uLong DxaEncoder::m13encode(byte *frame, byte *outbuf) {

byte *codeB = _codeBuf;
Expand Down
Loading