Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TOOLS: Restore support for DXA compression type 12 #68

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
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
Prev Previous commit
TOOLS: Restore support for DXA compression type 12
  • Loading branch information
ccawley2011 committed Apr 4, 2023
commit fe8c8da8424ac178dc13b24b48b9558f8f650a70
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