[Scummvm-cvs-logs] SF.net SVN: scummvm: [23334] tools/trunk/encode_dxa.cpp

kirben at users.sourceforge.net kirben at users.sourceforge.net
Wed Jun 28 16:11:11 CEST 2006


Revision: 23334
Author:   kirben
Date:     2006-06-28 07:11:07 -0700 (Wed, 28 Jun 2006)
ViewCVS:  http://svn.sourceforge.net/scummvm/?rev=23334&view=rev

Log Message:
-----------
Add patch #1504492 - DXA: New compression scheme

Modified Paths:
--------------
    tools/trunk/encode_dxa.cpp
Modified: tools/trunk/encode_dxa.cpp
===================================================================
--- tools/trunk/encode_dxa.cpp	2006-06-28 14:10:07 UTC (rev 23333)
+++ tools/trunk/encode_dxa.cpp	2006-06-28 14:11:07 UTC (rev 23334)
@@ -35,6 +35,10 @@
 
 #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 @@
 	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 @@
 		if (_framecount == 0)
 			compType = 2;
 		else
-			compType = 3;
+			//compType = 3;
+			compType = 12;
 
 		switch (compType) {
 		case 2:
@@ -169,6 +180,59 @@
 
 				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;
+			}
 		}
 
 		memcpy(_prevframe, frame, _width * _height);
@@ -180,6 +244,149 @@
 	_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];
 


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.





More information about the Scummvm-git-logs mailing list