[Scummvm-cvs-logs] SF.net SVN: scummvm:[35526] scummvm/trunk

drmccoy at users.sourceforge.net drmccoy at users.sourceforge.net
Wed Dec 24 16:57:43 CET 2008


Revision: 35526
          http://scummvm.svn.sourceforge.net/scummvm/?rev=35526&view=rev
Author:   drmccoy
Date:     2008-12-24 15:57:43 +0000 (Wed, 24 Dec 2008)

Log Message:
-----------
Moving the dither code to graphics/

Modified Paths:
--------------
    scummvm/trunk/engines/gob/coktelvideo.cpp
    scummvm/trunk/engines/gob/coktelvideo.h
    scummvm/trunk/engines/gob/indeo3.cpp
    scummvm/trunk/engines/gob/indeo3.h
    scummvm/trunk/engines/gob/inter_v6.cpp
    scummvm/trunk/engines/gob/video.cpp
    scummvm/trunk/engines/gob/video.h
    scummvm/trunk/engines/gob/video_v6.cpp
    scummvm/trunk/graphics/module.mk

Added Paths:
-----------
    scummvm/trunk/graphics/dither.cpp
    scummvm/trunk/graphics/dither.h

Modified: scummvm/trunk/engines/gob/coktelvideo.cpp
===================================================================
--- scummvm/trunk/engines/gob/coktelvideo.cpp	2008-12-24 15:30:31 UTC (rev 35525)
+++ scummvm/trunk/engines/gob/coktelvideo.cpp	2008-12-24 15:57:43 UTC (rev 35526)
@@ -25,6 +25,7 @@
 
 #include "common/endian.h"
 #include "common/system.h"
+#include "graphics/dither.h"
 
 #include "gob/coktelvideo.h"
 #include "gob/indeo3.h"
@@ -863,7 +864,7 @@
 	0x0F00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
 };
 
-Vmd::Vmd(PaletteLUT *palLUT) : _palLUT(palLUT) {
+Vmd::Vmd(Graphics::PaletteLUT *palLUT) : _palLUT(palLUT) {
 	clear(false);
 }
 
@@ -1540,7 +1541,8 @@
 
 	assert(_palLUT);
 
-	SierraLight *dither = new SierraLight(width, height, _palLUT);
+	Graphics::SierraLight *dither =
+		new Graphics::SierraLight(width, height, _palLUT);
 
 	for (int i = 0; i < height; i++) {
 		byte *d = dest;
@@ -1552,7 +1554,7 @@
 			byte b = ((*s & 0x001F) >>  0) << 1;
 			byte dY, dU, dV;
 
-			PaletteLUT::RGB2YUV(r << 2, g << 2, b << 2, dY, dU, dV);
+			Graphics::PaletteLUT::RGB2YUV(r << 2, g << 2, b << 2, dY, dU, dV);
 
 			byte p = dither->dither(dY, dU, dV, j);
 

Modified: scummvm/trunk/engines/gob/coktelvideo.h
===================================================================
--- scummvm/trunk/engines/gob/coktelvideo.h	2008-12-24 15:30:31 UTC (rev 35525)
+++ scummvm/trunk/engines/gob/coktelvideo.h	2008-12-24 15:57:43 UTC (rev 35526)
@@ -28,12 +28,13 @@
 
 #include "common/stream.h"
 #include "common/array.h"
+#include "graphics/dither.h"
 #include "sound/mixer.h"
 #include "sound/audiostream.h"
 
 namespace Gob {
 
-class PaletteLUT;
+class Graphics::PaletteLUT;
 class Indeo3;
 
 /** Common interface for handling Coktel Vision videos and derivated formats. */
@@ -303,7 +304,7 @@
 
 class Vmd : public Imd {
 public:
-	Vmd(PaletteLUT *palLUT = 0);
+	Vmd(Graphics::PaletteLUT *palLUT = 0);
 	~Vmd();
 
 	bool getAnchor(int16 frame, uint16 partType,
@@ -373,7 +374,7 @@
 	byte _scaleExternalX;
 	byte *_vidMemBuffer;
 
-	PaletteLUT *_palLUT;
+	Graphics::PaletteLUT *_palLUT;
 	Indeo3 *_codecIndeo3;
 
 	void clear(bool del = true);

Modified: scummvm/trunk/engines/gob/indeo3.cpp
===================================================================
--- scummvm/trunk/engines/gob/indeo3.cpp	2008-12-24 15:30:31 UTC (rev 35525)
+++ scummvm/trunk/engines/gob/indeo3.cpp	2008-12-24 15:57:43 UTC (rev 35526)
@@ -33,288 +33,20 @@
 #include "common/endian.h"
 #include "common/frac.h"
 #include "common/file.h"
+#include "graphics/dither.h"
 
 #include "gob/indeo3.h"
 #include "gob/indeo3data.h"
 
 namespace Gob {
 
-#define SQR(x) ((x) * (x))
-PaletteLUT::PaletteLUT(byte depth, PaletteFormat format) {
-	assert((depth > 1) && (depth < 9));
-
-	// For adjusting depth
-	_depth1 = depth;
-	_depth2 = 2 * _depth1;
-	_shift = 8 - _depth1;
-
-	// The table's dimensions
-	_dim1 = (1 << _depth1);
-	_dim2 = _dim1 * _dim1;
-	_dim3 = _dim1 * _dim1 * _dim1;
-
-	_format = format;
-
-	// What's already built
-	_got = _dim1;
-	_gots = new byte[_dim1];
-
-	// The lookup table
-	_lut = new byte[_dim3];
-
-	memset(_lutPal, 0, 768);
-	memset(_realPal, 0, 768);
-	memset(_gots, 1, _dim1);
-}
-
-void PaletteLUT::setPalette(const byte *palette, PaletteFormat format, byte depth) {
-	assert((depth > 1) && (depth < 9));
-
-	warning("Building new palette LUT");
-
-	int shift = 8 - depth;
-
-	// Checking for the table's and the palette's pixel format
-	if ((_format == kPaletteRGB) && (format == kPaletteYUV)) {
-		byte *newPal = _realPal;
-		const byte *oldPal = palette;
-		for (int i = 0; i < 256; i++, newPal += 3, oldPal += 3)
-			YUV2RGB(oldPal[0] << shift, oldPal[1] << shift, oldPal[2] << shift,
-					newPal[0], newPal[1], newPal[2]);
-	} else if ((_format == kPaletteYUV) && (format == kPaletteRGB)) {
-		byte *newPal = _realPal;
-		const byte *oldPal = palette;
-		for (int i = 0; i < 256; i++, newPal += 3, oldPal += 3)
-			RGB2YUV(oldPal[0] << shift, oldPal[1] << shift, oldPal[2] << shift,
-					newPal[0], newPal[1], newPal[2]);
-	} else
-		memcpy(_realPal, palette, 768);
-
-	// Using the specified depth for the lookup
-	byte *newPal = _lutPal, *oldPal = _realPal;
-	for (int i = 0; i < 768; i++)
-		*newPal++ = (*oldPal++) >> _shift;
-
-	// Everything has to be rebuilt
-	_got = 0;
-	memset(_gots, 0, _dim1);
-}
-
-PaletteLUT::~PaletteLUT() {
-	delete[] _lut;
-	delete[] _gots;
-}
-
-void PaletteLUT::buildNext() {
-	if (_got >= _dim1)
-		return;
-
-	build(_got++);
-}
-
-// Building one "slice"
-void PaletteLUT::build(int d1) {
-	// First dimension
-	byte *lut = _lut + d1 * _dim2;
-
-	// Second dimension
-	for (uint32 j = 0; j < _dim1; j++) {
-		// Third dimension
-		for (uint32 k = 0; k < _dim1; k++) {
-			const byte *p = _lutPal;
-			uint32 d = 0xFFFFFFFF;
-			byte n = 0;
-
-			// Going over every palette entry, searching for the closest
-			for (int c = 0; c < 256; c++, p += 3) {
-				uint32 di = SQR(d1 - p[0]) + SQR(j - p[1]) + SQR(k - p[2]);
-				if (di < d) {
-					d = di;
-					n = c;
-					if (d == 0)
-						break;
-				}
-			}
-
-			*lut++ = n;
-		}
-	}
-
-	// Got this slice now
-	_gots[d1] = 1;
-}
-
-inline int PaletteLUT::getIndex(byte c1, byte c2, byte c3) const {
-	return ((c1 >> _shift) << _depth2) | ((c2 >> _shift) << _depth1) | (c3 >> _shift);
-}
-
-void PaletteLUT::getEntry(byte index, byte &c1, byte &c2, byte &c3) const {
-	c1 = _realPal[index * 3 + 0];
-	c2 = _realPal[index * 3 + 1];
-	c3 = _realPal[index * 3 + 2];
-}
-
-byte PaletteLUT::findNearest(byte c1, byte c2, byte c3) {
-	return _lut[getIndex(c1, c2, c3)];
-}
-
-byte PaletteLUT::findNearest(byte c1, byte c2, byte c3, byte &nC1, byte &nC2, byte &nC3) {
-	// If we don't have the required "slice" yet, build it
-	if (!_gots[c1 >> _shift])
-		build(c1 >> _shift);
-
-	int palIndex = _lut[getIndex(c1, c2, c3)];
-	int i = palIndex * 3;
-
-	nC1 = _realPal[i + 0];
-	nC2 = _realPal[i + 1];
-	nC3 = _realPal[i + 2];
-
-	return palIndex;
-}
-
-bool PaletteLUT::save(Common::WriteStream &stream) {
-	// The table has to be completely built before we can save
-	while (_got < _dim1)
-		buildNext();
-
-	stream.writeByte(_depth1);
-	if (stream.write(_realPal, 768) != 768)
-		return false;
-	if (stream.write(_lutPal, 768) != 768)
-		return false;
-	if (stream.write(_lut, _dim3) != _dim3)
-		return false;
-	if (!stream.flush())
-		return false;
-
-	if (stream.err())
-		return false;
-
-	return true;
-}
-
-bool PaletteLUT::load(Common::SeekableReadStream &stream) {
-	//             _realPal + _lutPal + _lut  + _depth1
-	int32 needSize =  768   +   768   + _dim3 +    1;
-
-	if ((stream.size() - stream.pos()) < needSize)
-		return false;
-
-	byte depth1 = stream.readByte();
-
-	if (depth1 != _depth1)
-		return false;
-
-	if (stream.read(_realPal, 768) != 768)
-		return false;
-	if (stream.read(_lutPal, 768) != 768)
-		return false;
-	if (stream.read(_lut, _dim3) != _dim3)
-		return false;
-
-	_got = _dim1;
-	memset(_gots, 1, _dim1);
-
-	return true;
-}
-
-SierraLight::SierraLight(int16 width, int16 height, PaletteLUT *palLUT) {
+Indeo3::Indeo3(int16 width, int16 height, Graphics::PaletteLUT *palLUT) {
 	assert((width > 0) && (height > 0));
 
 	_width = width;
 	_height = height;
 	_palLUT = palLUT;
 
-	// Big buffer for the errors of the current and next line
-	_errorBuf = new int32[3 * (2 * (_width + 2*1))];
-	memset(_errorBuf, 0, (3 * (2 * (_width + 2*1))) * sizeof(int32));
-
-	_curLine = 0;
-	_errors[0] = _errorBuf + 3;
-	_errors[1] = _errors[0] + 3 * (_width + 2*1);
-}
-
-SierraLight::~SierraLight() {
-	delete[] _errorBuf;
-}
-
-void SierraLight::newFrame() {
-	_curLine = 0;
-	memset(_errors[0], 0, 3 * _width * sizeof(int32));
-	memset(_errors[1], 0, 3 * _width * sizeof(int32));
-}
-
-void SierraLight::nextLine() {
-	// Clear the finished line, it will become the last line in the buffer
-	memset(_errors[_curLine], 0, 3 * _width * sizeof(int32));
-
-	_curLine = (_curLine + 1) % 2;
-}
-
-byte SierraLight::dither(byte c1, byte c2, byte c3, uint32 x) {
-	assert(_palLUT);
-
-	int32 eC1, eC2, eC3;
-
-	getErrors(x, eC1, eC2, eC3);
-
-	// Apply error on values
-	c1 = CLIP<int>(c1 + eC1, 0, 255);
-	c2 = CLIP<int>(c2 + eC2, 0, 255);
-	c3 = CLIP<int>(c3 + eC3, 0, 255);
-
-	// Find color
-	byte newC1, newC2, newC3;
-	byte newPixel = _palLUT->findNearest(c1, c2, c3, newC1, newC2, newC3);
-
-	// Calculate new error
-	eC1 = c1 - newC1;
-	eC2 = c2 - newC2;
-	eC3 = c3 - newC3;
-
-	// Add them
-	addErrors(x, eC1, eC2, eC3);
-
-	return newPixel;
-}
-
-inline void SierraLight::getErrors(uint32 x, int32 &eC1, int32 &eC2, int32 &eC3) {
-	int32 *errCur = _errors[_curLine];
-
-	x *= 3;
-	eC1 = errCur[x + 0] >> 2;
-	eC2 = errCur[x + 1] >> 2;
-	eC3 = errCur[x + 2] >> 2;
-}
-
-inline void SierraLight::addErrors(uint32 x, int32 eC1, int32 eC2, int32 eC3) {
-	int32 *errCur  = _errors[_curLine];
-	int32 *errNext = _errors[(_curLine + 1) % 2];
-
-	// Indices for current error
-	int x0 = 3 * (x + 1);
-	int x1 = 3 * (x + 0);
-	int x2 = 3 * (x - 1);
-
-	errCur [x0 + 0] += eC1 << 1;
-	errCur [x0 + 1] += eC2 << 1;
-	errCur [x0 + 2] += eC3 << 1;
-	errNext[x1 + 0] += eC1;
-	errNext[x1 + 1] += eC2;
-	errNext[x1 + 2] += eC3;
-	errNext[x2 + 0] += eC1;
-	errNext[x2 + 1] += eC2;
-	errNext[x2 + 2] += eC3;
-}
-
-Indeo3::Indeo3(int16 width, int16 height, PaletteLUT *palLUT) {
-	assert((width > 0) && (height > 0));
-
-	_width = width;
-	_height = height;
-	_palLUT = palLUT;
-
 	_ditherSL = 0;
 	setDither(kDitherSierraLight);
 
@@ -363,7 +95,7 @@
 
 	switch(dither) {
 	case kDitherSierraLight:
-		_ditherSL = new SierraLight(_width, _height, _palLUT);
+		_ditherSL = new Graphics::SierraLight(_width, _height, _palLUT);
 		break;
 
 	default:

Modified: scummvm/trunk/engines/gob/indeo3.h
===================================================================
--- scummvm/trunk/engines/gob/indeo3.h	2008-12-24 15:30:31 UTC (rev 35525)
+++ scummvm/trunk/engines/gob/indeo3.h	2008-12-24 15:57:43 UTC (rev 35526)
@@ -35,82 +35,13 @@
 
 #include "common/stream.h"
 
+namespace Graphics {
+	class PaletteLUT;
+	class SierraLight;
+}
+
 namespace Gob {
 
-class PaletteLUT {
-public:
-	enum PaletteFormat {
-		kPaletteRGB,
-		kPaletteYUV
-	};
-
-	inline static void YUV2RGB(byte y, byte u, byte v, byte &r, byte &g, byte &b) {
-		r = CLIP<int>(y + ((1357 * (v - 128)) >> 10), 0, 255);
-		g = CLIP<int>(y - (( 691 * (v - 128)) >> 10) - ((333 * (u - 128)) >> 10), 0, 255);
-		b = CLIP<int>(y + ((1715 * (u - 128)) >> 10), 0, 255);
-	}
-	inline static void RGB2YUV(byte r, byte g, byte b, byte &y, byte &u, byte &v) {
-		y = CLIP<int>( ((r * 306) >> 10) + ((g * 601) >> 10) + ((b * 117) >> 10)      , 0, 255);
-		u = CLIP<int>(-((r * 172) >> 10) - ((g * 340) >> 10) + ((b * 512) >> 10) + 128, 0, 255);
-		v = CLIP<int>( ((r * 512) >> 10) - ((g * 429) >> 10) - ((b *  83) >> 10) + 128, 0, 255);
-	}
-
-	PaletteLUT(byte depth, PaletteFormat format);
-	~PaletteLUT();
-
-	void setPalette(const byte *palette, PaletteFormat format, byte depth);
-
-	void buildNext();
-
-	void getEntry(byte index, byte &c1, byte &c2, byte &c3) const;
-	byte findNearest(byte c1, byte c2, byte c3);
-	byte findNearest(byte c1, byte c2, byte c3, byte &nC1, byte &nC2, byte &nC3);
-
-	bool save(Common::WriteStream &stream);
-	bool load(Common::SeekableReadStream &stream);
-
-private:
-	byte _depth1, _depth2;
-	byte _shift;
-
-	uint32 _dim1, _dim2, _dim3;
-
-	PaletteFormat _format;
-	byte _lutPal[768];
-	byte _realPal[768];
-
-	uint32 _got;
-	byte *_gots;
-	byte *_lut;
-
-	void build(int d1);
-	inline int getIndex(byte c1, byte c2, byte c3) const;
-	inline void plotEntry(int x, int y, int z, byte e, byte *filled, int &free);
-};
-
-// The Sierra-2-4A ("Filter Light") dithering algorithm
-class SierraLight {
-public:
-	SierraLight(int16 width, int16 height, PaletteLUT *palLUT);
-	~SierraLight();
-
-	void newFrame();
-	void nextLine();
-	byte dither(byte c1, byte c2, byte c3, uint32 x);
-
-protected:
-	int16 _width, _height;
-
-	PaletteLUT *_palLUT;
-
-	int32 *_errorBuf;
-	int32 *_errors[2];
-	int _curLine;
-
-	inline void getErrors(uint32 x, int32 &eC1, int32 &eC2, int32 &eC3);
-	inline void addErrors(uint32 x, int32 eC1, int32 eC2, int32 eC3);
-};
-
 class Indeo3 {
 public:
 	enum DitherAlgorithm {
@@ -118,7 +49,7 @@
 		kDitherSierraLight
 	};
 
-	Indeo3(int16 width, int16 height, PaletteLUT *palLUT);
+	Indeo3(int16 width, int16 height, Graphics::PaletteLUT *palLUT);
 	~Indeo3();
 
 	static bool isIndeo3(byte *data, uint32 dataLen);
@@ -154,10 +85,10 @@
 	byte *_ModPred;
 	uint16 *_corrector_type;
 
-	PaletteLUT *_palLUT;
+	Graphics::PaletteLUT *_palLUT;
 
 	DitherAlgorithm _dither;
-	SierraLight *_ditherSL;
+	Graphics::SierraLight *_ditherSL;
 
 	struct BlitState {
 		uint32 curX, curY;

Modified: scummvm/trunk/engines/gob/inter_v6.cpp
===================================================================
--- scummvm/trunk/engines/gob/inter_v6.cpp	2008-12-24 15:30:31 UTC (rev 35525)
+++ scummvm/trunk/engines/gob/inter_v6.cpp	2008-12-24 15:57:43 UTC (rev 35526)
@@ -25,6 +25,7 @@
 
 #include "common/endian.h"
 #include "common/file.h"
+#include "graphics/dither.h"
 
 #include "gob/gob.h"
 #include "gob/inter.h"
@@ -926,7 +927,7 @@
 
 	if (_gotFirstPalette)
 		_vm->_video->_palLUT->setPalette((const byte *) _vm->_global->_pPaletteDesc->vgaPal,
-				PaletteLUT::kPaletteRGB, 6);
+				Graphics::PaletteLUT::kPaletteRGB, 6);
 
 	_gotFirstPalette = true;
 	return false;

Modified: scummvm/trunk/engines/gob/video.cpp
===================================================================
--- scummvm/trunk/engines/gob/video.cpp	2008-12-24 15:30:31 UTC (rev 35525)
+++ scummvm/trunk/engines/gob/video.cpp	2008-12-24 15:57:43 UTC (rev 35526)
@@ -27,6 +27,7 @@
 #include "graphics/cursorman.h"
 #include "graphics/fontman.h"
 #include "graphics/surface.h"
+#include "graphics/dither.h"
 
 #include "gob/gob.h"
 #include "gob/video.h"
@@ -109,7 +110,7 @@
 
 	_dirtyAll = false;
 
-	_palLUT = new PaletteLUT(6, PaletteLUT::kPaletteYUV);
+	_palLUT = new Graphics::PaletteLUT(6, Graphics::PaletteLUT::kPaletteYUV);
 }
 
 char Video::initDriver(int16 vidMode) {

Modified: scummvm/trunk/engines/gob/video.h
===================================================================
--- scummvm/trunk/engines/gob/video.h	2008-12-24 15:30:31 UTC (rev 35525)
+++ scummvm/trunk/engines/gob/video.h	2008-12-24 15:57:43 UTC (rev 35526)
@@ -31,9 +31,13 @@
 
 #include "gob/gob.h"
 
+namespace Graphics {
+	class PaletteLUT;
+}
+
 namespace Gob {
 
-class PaletteLUT;
+class Graphics::PaletteLUT;
 
 // Some Surfaces are simultaneous in Draw::spritesArray and discrete
 // variables, so it's a references counting class that cleans
@@ -122,7 +126,7 @@
 	int16 _screenDeltaX;
 	int16 _screenDeltaY;
 
-	PaletteLUT *_palLUT;
+	Graphics::PaletteLUT *_palLUT;
 
 	void freeDriver();
 	void initPrimary(int16 mode);

Modified: scummvm/trunk/engines/gob/video_v6.cpp
===================================================================
--- scummvm/trunk/engines/gob/video_v6.cpp	2008-12-24 15:30:31 UTC (rev 35525)
+++ scummvm/trunk/engines/gob/video_v6.cpp	2008-12-24 15:57:43 UTC (rev 35526)
@@ -25,6 +25,7 @@
 
 #include "common/endian.h"
 #include "common/savefile.h"
+#include "graphics/dither.h"
 
 #include "gob/gob.h"
 #include "gob/video.h"
@@ -104,7 +105,7 @@
 void Video_v6::buildPalLUT() {
 	char text[30];
 
-	_palLUT->setPalette(_ditherPalette, PaletteLUT::kPaletteYUV, 8);
+	_palLUT->setPalette(_ditherPalette, Graphics::PaletteLUT::kPaletteYUV, 8);
 
 	for (int i = 0; (i < 64) && !_vm->shouldQuit(); i++) {
 		sprintf(text, "Building palette table: %02d/63", i);
@@ -175,7 +176,8 @@
 
 	_palLUT->getEntry(color, sY, sU, sV);
 
-	SierraLight *dither = new SierraLight(width, height, _palLUT);
+	Graphics::SierraLight *dither =
+		new Graphics::SierraLight(width, height, _palLUT);
 
 	for (int i = 0; i < height; i++) {
 		byte *d = vidMem;
@@ -253,7 +255,8 @@
 	if ((y + height - 1) >= destDesc->getHeight())
 		height = destDesc->getHeight() - y;
 
-	SierraLight *dither = new SierraLight(width, height, _palLUT);
+	Graphics::SierraLight *dither =
+		new Graphics::SierraLight(width, height, _palLUT);
 
 	for (int i = 0; i < height; i++) {
 		byte *dest = vidMem;

Added: scummvm/trunk/graphics/dither.cpp
===================================================================
--- scummvm/trunk/graphics/dither.cpp	                        (rev 0)
+++ scummvm/trunk/graphics/dither.cpp	2008-12-24 15:57:43 UTC (rev 35526)
@@ -0,0 +1,296 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "graphics/dither.h"
+
+namespace Graphics {
+
+PaletteLUT::PaletteLUT(byte depth, PaletteFormat format) {
+	assert((depth > 1) && (depth < 9));
+
+	// For adjusting depth
+	_depth1 = depth;
+	_depth2 = 2 * _depth1;
+	_shift = 8 - _depth1;
+
+	// The table's dimensions
+	_dim1 = (1 << _depth1);
+	_dim2 = _dim1 * _dim1;
+	_dim3 = _dim1 * _dim1 * _dim1;
+
+	_format = format;
+
+	// What's already built
+	_got = _dim1;
+	_gots = new byte[_dim1];
+
+	// The lookup table
+	_lut = new byte[_dim3];
+
+	memset(_lutPal, 0, 768);
+	memset(_realPal, 0, 768);
+	memset(_gots, 1, _dim1);
+}
+
+void PaletteLUT::setPalette(const byte *palette, PaletteFormat format, byte depth) {
+	assert((depth > 1) && (depth < 9));
+
+	int shift = 8 - depth;
+
+	// Checking for the table's and the palette's pixel format
+	if ((_format == kPaletteRGB) && (format == kPaletteYUV)) {
+		byte *newPal = _realPal;
+		const byte *oldPal = palette;
+		for (int i = 0; i < 256; i++, newPal += 3, oldPal += 3)
+			YUV2RGB(oldPal[0] << shift, oldPal[1] << shift, oldPal[2] << shift,
+					newPal[0], newPal[1], newPal[2]);
+	} else if ((_format == kPaletteYUV) && (format == kPaletteRGB)) {
+		byte *newPal = _realPal;
+		const byte *oldPal = palette;
+		for (int i = 0; i < 256; i++, newPal += 3, oldPal += 3)
+			RGB2YUV(oldPal[0] << shift, oldPal[1] << shift, oldPal[2] << shift,
+					newPal[0], newPal[1], newPal[2]);
+	} else
+		memcpy(_realPal, palette, 768);
+
+	// Using the specified depth for the lookup
+	byte *newPal = _lutPal, *oldPal = _realPal;
+	for (int i = 0; i < 768; i++)
+		*newPal++ = (*oldPal++) >> _shift;
+
+	// Everything has to be rebuilt
+	_got = 0;
+	memset(_gots, 0, _dim1);
+}
+
+PaletteLUT::~PaletteLUT() {
+	delete[] _lut;
+	delete[] _gots;
+}
+
+void PaletteLUT::buildNext() {
+	if (_got >= _dim1)
+		return;
+
+	build(_got++);
+}
+
+#define SQR(x) ((x) * (x))
+// Building one "slice"
+void PaletteLUT::build(int d1) {
+	// First dimension
+	byte *lut = _lut + d1 * _dim2;
+
+	// Second dimension
+	for (uint32 j = 0; j < _dim1; j++) {
+		// Third dimension
+		for (uint32 k = 0; k < _dim1; k++) {
+			const byte *p = _lutPal;
+			uint32 d = 0xFFFFFFFF;
+			byte n = 0;
+
+			// Going over every palette entry, searching for the closest
+			for (int c = 0; c < 256; c++, p += 3) {
+				uint32 di = SQR(d1 - p[0]) + SQR(j - p[1]) + SQR(k - p[2]);
+				if (di < d) {
+					d = di;
+					n = c;
+					if (d == 0)
+						break;
+				}
+			}
+
+			*lut++ = n;
+		}
+	}
+
+	// Got this slice now
+	_gots[d1] = 1;
+}
+
+inline int PaletteLUT::getIndex(byte c1, byte c2, byte c3) const {
+	return ((c1 >> _shift) << _depth2) | ((c2 >> _shift) << _depth1) | (c3 >> _shift);
+}
+
+void PaletteLUT::getEntry(byte index, byte &c1, byte &c2, byte &c3) const {
+	c1 = _realPal[index * 3 + 0];
+	c2 = _realPal[index * 3 + 1];
+	c3 = _realPal[index * 3 + 2];
+}
+
+byte PaletteLUT::findNearest(byte c1, byte c2, byte c3) {
+	return _lut[getIndex(c1, c2, c3)];
+}
+
+byte PaletteLUT::findNearest(byte c1, byte c2, byte c3, byte &nC1, byte &nC2, byte &nC3) {
+	// If we don't have the required "slice" yet, build it
+	if (!_gots[c1 >> _shift])
+		build(c1 >> _shift);
+
+	int palIndex = _lut[getIndex(c1, c2, c3)];
+	int i = palIndex * 3;
+
+	nC1 = _realPal[i + 0];
+	nC2 = _realPal[i + 1];
+	nC3 = _realPal[i + 2];
+
+	return palIndex;
+}
+
+bool PaletteLUT::save(Common::WriteStream &stream) {
+	// The table has to be completely built before we can save
+	while (_got < _dim1)
+		buildNext();
+
+	stream.writeByte(_depth1);
+	if (stream.write(_realPal, 768) != 768)
+		return false;
+	if (stream.write(_lutPal, 768) != 768)
+		return false;
+	if (stream.write(_lut, _dim3) != _dim3)
+		return false;
+	if (!stream.flush())
+		return false;
+
+	if (stream.err())
+		return false;
+
+	return true;
+}
+
+bool PaletteLUT::load(Common::SeekableReadStream &stream) {
+	//             _realPal + _lutPal + _lut  + _depth1
+	int32 needSize =  768   +   768   + _dim3 +    1;
+
+	if ((stream.size() - stream.pos()) < needSize)
+		return false;
+
+	byte depth1 = stream.readByte();
+
+	if (depth1 != _depth1)
+		return false;
+
+	if (stream.read(_realPal, 768) != 768)
+		return false;
+	if (stream.read(_lutPal, 768) != 768)
+		return false;
+	if (stream.read(_lut, _dim3) != _dim3)
+		return false;
+
+	_got = _dim1;
+	memset(_gots, 1, _dim1);
+
+	return true;
+}
+
+SierraLight::SierraLight(int16 width, int16 height, PaletteLUT *palLUT) {
+	assert((width > 0) && (height > 0));
+
+	_width = width;
+	_height = height;
+	_palLUT = palLUT;
+
+	// Big buffer for the errors of the current and next line
+	_errorBuf = new int32[3 * (2 * (_width + 2*1))];
+	memset(_errorBuf, 0, (3 * (2 * (_width + 2*1))) * sizeof(int32));
+
+	_curLine = 0;
+	_errors[0] = _errorBuf + 3;
+	_errors[1] = _errors[0] + 3 * (_width + 2*1);
+}
+
+SierraLight::~SierraLight() {
+	delete[] _errorBuf;
+}
+
+void SierraLight::newFrame() {
+	_curLine = 0;
+	memset(_errors[0], 0, 3 * _width * sizeof(int32));
+	memset(_errors[1], 0, 3 * _width * sizeof(int32));
+}
+
+void SierraLight::nextLine() {
+	// Clear the finished line, it will become the last line in the buffer
+	memset(_errors[_curLine], 0, 3 * _width * sizeof(int32));
+
+	_curLine = (_curLine + 1) % 2;
+}
+
+byte SierraLight::dither(byte c1, byte c2, byte c3, uint32 x) {
+	assert(_palLUT);
+
+	int32 eC1, eC2, eC3;
+
+	getErrors(x, eC1, eC2, eC3);
+
+	// Apply error on values
+	c1 = CLIP<int>(c1 + eC1, 0, 255);
+	c2 = CLIP<int>(c2 + eC2, 0, 255);
+	c3 = CLIP<int>(c3 + eC3, 0, 255);
+
+	// Find color
+	byte newC1, newC2, newC3;
+	byte newPixel = _palLUT->findNearest(c1, c2, c3, newC1, newC2, newC3);
+
+	// Calculate new error
+	eC1 = c1 - newC1;
+	eC2 = c2 - newC2;
+	eC3 = c3 - newC3;
+
+	// Add them
+	addErrors(x, eC1, eC2, eC3);
+
+	return newPixel;
+}
+
+inline void SierraLight::getErrors(uint32 x, int32 &eC1, int32 &eC2, int32 &eC3) {
+	int32 *errCur = _errors[_curLine];
+
+	x *= 3;
+	eC1 = errCur[x + 0] >> 2;
+	eC2 = errCur[x + 1] >> 2;
+	eC3 = errCur[x + 2] >> 2;
+}
+
+inline void SierraLight::addErrors(uint32 x, int32 eC1, int32 eC2, int32 eC3) {
+	int32 *errCur  = _errors[_curLine];
+	int32 *errNext = _errors[(_curLine + 1) % 2];
+
+	// Indices for current error
+	int x0 = 3 * (x + 1);
+	int x1 = 3 * (x + 0);
+	int x2 = 3 * (x - 1);
+
+	errCur [x0 + 0] += eC1 << 1;
+	errCur [x0 + 1] += eC2 << 1;
+	errCur [x0 + 2] += eC3 << 1;
+	errNext[x1 + 0] += eC1;
+	errNext[x1 + 1] += eC2;
+	errNext[x1 + 2] += eC3;
+	errNext[x2 + 0] += eC1;
+	errNext[x2 + 1] += eC2;
+	errNext[x2 + 2] += eC3;
+}
+
+} // End of namespace Graphics


Property changes on: scummvm/trunk/graphics/dither.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: scummvm/trunk/graphics/dither.h
===================================================================
--- scummvm/trunk/graphics/dither.h	                        (rev 0)
+++ scummvm/trunk/graphics/dither.h	2008-12-24 15:57:43 UTC (rev 35526)
@@ -0,0 +1,109 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef GRAPHICS_DITHER_H
+#define GRAPHICS_DITHER_H
+
+#include "common/util.h"
+#include "common/stream.h"
+
+namespace Graphics {
+
+class PaletteLUT {
+public:
+	enum PaletteFormat {
+		kPaletteRGB,
+		kPaletteYUV
+	};
+
+	inline static void YUV2RGB(byte y, byte u, byte v, byte &r, byte &g, byte &b) {
+		r = CLIP<int>(y + ((1357 * (v - 128)) >> 10), 0, 255);
+		g = CLIP<int>(y - (( 691 * (v - 128)) >> 10) - ((333 * (u - 128)) >> 10), 0, 255);
+		b = CLIP<int>(y + ((1715 * (u - 128)) >> 10), 0, 255);
+	}
+	inline static void RGB2YUV(byte r, byte g, byte b, byte &y, byte &u, byte &v) {
+		y = CLIP<int>( ((r * 306) >> 10) + ((g * 601) >> 10) + ((b * 117) >> 10)      , 0, 255);
+		u = CLIP<int>(-((r * 172) >> 10) - ((g * 340) >> 10) + ((b * 512) >> 10) + 128, 0, 255);
+		v = CLIP<int>( ((r * 512) >> 10) - ((g * 429) >> 10) - ((b *  83) >> 10) + 128, 0, 255);
+	}
+
+	PaletteLUT(byte depth, PaletteFormat format);
+	~PaletteLUT();
+
+	void setPalette(const byte *palette, PaletteFormat format, byte depth);
+
+	void buildNext();
+
+	void getEntry(byte index, byte &c1, byte &c2, byte &c3) const;
+	byte findNearest(byte c1, byte c2, byte c3);
+	byte findNearest(byte c1, byte c2, byte c3, byte &nC1, byte &nC2, byte &nC3);
+
+	bool save(Common::WriteStream &stream);
+	bool load(Common::SeekableReadStream &stream);
+
+private:
+	byte _depth1, _depth2;
+	byte _shift;
+
+	uint32 _dim1, _dim2, _dim3;
+
+	PaletteFormat _format;
+	byte _lutPal[768];
+	byte _realPal[768];
+
+	uint32 _got;
+	byte *_gots;
+	byte *_lut;
+
+	void build(int d1);
+	inline int getIndex(byte c1, byte c2, byte c3) const;
+	inline void plotEntry(int x, int y, int z, byte e, byte *filled, int &free);
+};
+
+// The Sierra-2-4A ("Filter Light") dithering algorithm
+class SierraLight {
+public:
+	SierraLight(int16 width, int16 height, PaletteLUT *palLUT);
+	~SierraLight();
+
+	void newFrame();
+	void nextLine();
+	byte dither(byte c1, byte c2, byte c3, uint32 x);
+
+protected:
+	int16 _width, _height;
+
+	PaletteLUT *_palLUT;
+
+	int32 *_errorBuf;
+	int32 *_errors[2];
+	int _curLine;
+
+	inline void getErrors(uint32 x, int32 &eC1, int32 &eC2, int32 &eC3);
+	inline void addErrors(uint32 x, int32 eC1, int32 eC2, int32 eC3);
+};
+
+} // End of namespace Graphics
+
+#endif


Property changes on: scummvm/trunk/graphics/dither.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Modified: scummvm/trunk/graphics/module.mk
===================================================================
--- scummvm/trunk/graphics/module.mk	2008-12-24 15:30:31 UTC (rev 35525)
+++ scummvm/trunk/graphics/module.mk	2008-12-24 15:57:43 UTC (rev 35526)
@@ -2,6 +2,7 @@
 
 MODULE_OBJS := \
 	cursorman.o \
+	dither.o \
 	font.o \
 	fontman.o \
 	fonts/consolefont.o \


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