mirror of
https://github.com/scummvm/scummvm-tools.git
synced 2026-05-21 05:40:44 +00:00
+208
-1
@@ -35,6 +35,10 @@ const uint32 typeNULL = 0x4C4C554E;
|
||||
|
||||
#define BUFFER_LEN 1024
|
||||
|
||||
// other block dimensions than 4x4 are not really supported yet
|
||||
#define BLOCKW 4
|
||||
#define BLOCKH 4
|
||||
|
||||
static CompressMode gCompMode = kMP3Mode;
|
||||
|
||||
class DxaEncoder {
|
||||
@@ -43,6 +47,12 @@ private:
|
||||
int _width, _height, _framerate, _framecount;
|
||||
uint8 *_prevframe, *_prevpalette;
|
||||
|
||||
bool m12blocksAreEqual(byte *frame, int x, int y, int x2, int y2);
|
||||
bool m12blockIsSolidColor(byte *frame, int x, int y, byte &color);
|
||||
void m12blockDelta(byte *frame, int x, int y, unsigned short &diffMap, int &diffCount, byte diffPix[]);
|
||||
bool m12motionVector(byte *frame, int x, int y, int &mx, int &my);
|
||||
uLong m12encode(byte *frame, byte *outbuf);
|
||||
|
||||
public:
|
||||
DxaEncoder(char *filename, int width, int height, int fps);
|
||||
~DxaEncoder();
|
||||
@@ -111,7 +121,8 @@ void DxaEncoder::writeFrame(uint8 *frame, uint8 *palette) {
|
||||
if (_framecount == 0)
|
||||
compType = 2;
|
||||
else
|
||||
compType = 3;
|
||||
//compType = 3;
|
||||
compType = 12;
|
||||
|
||||
switch (compType) {
|
||||
case 2:
|
||||
@@ -167,6 +178,59 @@ void DxaEncoder::writeFrame(uint8 *frame, uint8 *palette) {
|
||||
delete[] outbuf2;
|
||||
delete[] xorbuf;
|
||||
|
||||
break;
|
||||
}
|
||||
case 12:
|
||||
|
||||
{
|
||||
|
||||
uLong outsize1 = _width * _height;
|
||||
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 * _height];
|
||||
|
||||
for (int i = 0; i < _width * _height; i++)
|
||||
xorbuf[i] = _prevframe[i] ^ frame[i];
|
||||
|
||||
compress2(outbuf1, &outsize1, xorbuf, _width * _height, 9);
|
||||
compress2(outbuf2, &outsize2, frame, _width * _height, 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;
|
||||
}
|
||||
|
||||
writeByte(_dxa, compType);
|
||||
writeUint32BE(_dxa, outsize);
|
||||
fwrite(outbuf, outsize, 1, _dxa);
|
||||
|
||||
delete[] outbuf1;
|
||||
delete[] outbuf2;
|
||||
delete[] outbuf3;
|
||||
delete[] outbuf4;
|
||||
delete[] xorbuf;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -180,6 +244,149 @@ void DxaEncoder::writeFrame(uint8 *frame, uint8 *palette) {
|
||||
_framecount++;
|
||||
}
|
||||
|
||||
bool DxaEncoder::m12blocksAreEqual(byte *frame, int x, int y, int x2, int y2) {
|
||||
byte *b1 = _prevframe + x + y * _width;
|
||||
byte *b2 = frame + x2 + y2 * _width;
|
||||
for (int yc = 0; yc < BLOCKH; yc++) {
|
||||
if (memcmp(b1, b2, BLOCKW))
|
||||
return false;
|
||||
b1 += _width;
|
||||
b2 += _width;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DxaEncoder::m12blockIsSolidColor(byte *frame, int x, int y, byte &color) {
|
||||
byte *b2 = frame + x + y * _width;
|
||||
color = *b2;
|
||||
for (int yc = 0; yc < BLOCKH; yc++) {
|
||||
for (int xc = 0; xc < BLOCKW; xc++) {
|
||||
if (b2[xc] != color)
|
||||
return false;
|
||||
}
|
||||
b2 += _width;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DxaEncoder::m12blockDelta(byte *frame, int x, int y, unsigned short &diffMap, int &diffCount, byte diffPix[]) {
|
||||
byte *b1 = _prevframe + x + y * _width;
|
||||
byte *b2 = frame + x + y * _width;
|
||||
diffCount = 0;
|
||||
diffMap = 0;
|
||||
for (int yc = 0; yc < BLOCKH; yc++) {
|
||||
for (int xc = 0; xc < BLOCKW; xc++) {
|
||||
if (b1[xc] != b2[xc]) {
|
||||
diffMap = (diffMap << 1) | 1;
|
||||
diffPix[diffCount++] = b2[xc];
|
||||
} else {
|
||||
diffMap = (diffMap << 1) | 0;
|
||||
}
|
||||
}
|
||||
b1 += _width;
|
||||
b2 += _width;
|
||||
}
|
||||
}
|
||||
|
||||
bool DxaEncoder::m12motionVector(byte *frame, int x, int y, int &mx, int &my) {
|
||||
int xmin = (0 > x-7) ? 0 : x-7;
|
||||
int ymin = (0 > y-7) ? 0 : y-7;
|
||||
int xmax = (_width < x+8) ? _width : x+8;
|
||||
int ymax = (_height < y+8) ? _height : y+8;
|
||||
for (int yc = ymin; yc < ymax; yc++) {
|
||||
for (int xc = xmin; xc < xmax; xc++) {
|
||||
if (m12blocksAreEqual(frame, xc, yc, x, y)) {
|
||||
mx = xc - x;
|
||||
my = yc - y;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uLong DxaEncoder::m12encode(byte *frame, byte *outbuf) {
|
||||
byte *outb = outbuf;
|
||||
byte color;
|
||||
int mx, my;
|
||||
unsigned short diffMap;
|
||||
int diffCount;
|
||||
byte diffPix[BLOCKW*BLOCKH];
|
||||
|
||||
for (int by = 0; by < _height; by += BLOCKH) {
|
||||
for (int bx = 0; bx < _width; bx += BLOCKW) {
|
||||
if (m12blocksAreEqual(frame, bx, by, bx, by)) {
|
||||
*outb++ = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m12blockIsSolidColor(frame, bx, by, color)) {
|
||||
*outb++ = 2;
|
||||
*outb++ = color;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m12motionVector(frame, bx, by, 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;
|
||||
}
|
||||
|
||||
m12blockDelta(frame, bx, by, diffMap, diffCount, diffPix);
|
||||
|
||||
if (diffCount >= 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 ((diffMap & maskTbl[m].mask) == 0) {
|
||||
smallMask = true;
|
||||
*outb++ = 10 + m;
|
||||
*outb++ = ((diffMap >> maskTbl[m].sh1) & 0xF0) | ((diffMap >> maskTbl[m].sh2) & 0x0F);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!smallMask) {
|
||||
*outb++ = 1;
|
||||
*(unsigned short*)outb = diffMap;
|
||||
outb += 2;
|
||||
}
|
||||
|
||||
memcpy(outb, diffPix, diffCount);
|
||||
outb += diffCount;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outb - outbuf;
|
||||
}
|
||||
|
||||
int read_png_file(char* filename, unsigned char *&image, unsigned char *&palette, int &width, int &height) {
|
||||
png_byte header[8];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user