[Scummvm-cvs-logs] scummvm master -> 09269fce8c61b8193b25266b681c7849a6ad058d

clone2727 clone2727 at gmail.com
Tue Sep 18 22:56:46 CEST 2012


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
09269fce8c GRAPHICS: Implement different luminance ranges


Commit: 09269fce8c61b8193b25266b681c7849a6ad058d
    https://github.com/scummvm/scummvm/commit/09269fce8c61b8193b25266b681c7849a6ad058d
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2012-09-18T13:50:01-07:00

Commit Message:
GRAPHICS: Implement different luminance ranges

Bink and Theora are now much improved

Changed paths:
    graphics/decoders/jpeg.cpp
    graphics/yuv_to_rgb.cpp
    graphics/yuv_to_rgb.h
    video/bink_decoder.cpp
    video/codecs/svq1.cpp
    video/psx_decoder.cpp
    video/theora_decoder.cpp



diff --git a/graphics/decoders/jpeg.cpp b/graphics/decoders/jpeg.cpp
index 77ca316..748275b 100644
--- a/graphics/decoders/jpeg.cpp
+++ b/graphics/decoders/jpeg.cpp
@@ -81,7 +81,7 @@ const Surface *JPEGDecoder::getSurface() const {
 	const Graphics::Surface *uComponent = getComponent(2);
 	const Graphics::Surface *vComponent = getComponent(3);
 
-	YUVToRGBMan.convert444(_rgbSurface, (byte *)yComponent->pixels, (byte *)uComponent->pixels, (byte *)vComponent->pixels, yComponent->w, yComponent->h, yComponent->pitch, uComponent->pitch);
+	YUVToRGBMan.convert444(_rgbSurface, Graphics::YUVToRGBManager::kScaleFull, (byte *)yComponent->pixels, (byte *)uComponent->pixels, (byte *)vComponent->pixels, yComponent->w, yComponent->h, yComponent->pitch, uComponent->pitch);
 
 	return _rgbSurface;
 }
diff --git a/graphics/yuv_to_rgb.cpp b/graphics/yuv_to_rgb.cpp
index 1afd0d2..6043315 100644
--- a/graphics/yuv_to_rgb.cpp
+++ b/graphics/yuv_to_rgb.cpp
@@ -94,40 +94,67 @@ namespace Graphics {
 
 class YUVToRGBLookup {
 public:
-	YUVToRGBLookup(Graphics::PixelFormat format);
-	~YUVToRGBLookup();
+	YUVToRGBLookup(Graphics::PixelFormat format, YUVToRGBManager::LuminanceScale scale);
 
-	uint32 *_rgbToPix;
+	Graphics::PixelFormat getFormat() const { return _format; }
+	YUVToRGBManager::LuminanceScale getScale() const { return _scale; }
+	const uint32 *getRGBToPix() const { return _rgbToPix; }
+
+private:
+	Graphics::PixelFormat _format;
+	YUVToRGBManager::LuminanceScale _scale;
+	uint32 _rgbToPix[3 * 768]; // 9216 bytes
 };
 
-YUVToRGBLookup::YUVToRGBLookup(Graphics::PixelFormat format) {
-	_rgbToPix = new uint32[3 * 768]; // 9216 bytes
+YUVToRGBLookup::YUVToRGBLookup(Graphics::PixelFormat format, YUVToRGBManager::LuminanceScale scale) {
+	_format = format;
+	_scale = scale;
 
 	uint32 *r_2_pix_alloc = &_rgbToPix[0 * 768];
 	uint32 *g_2_pix_alloc = &_rgbToPix[1 * 768];
 	uint32 *b_2_pix_alloc = &_rgbToPix[2 * 768];
 
-	// Set up entries 0-255 in rgb-to-pixel value tables.
-	for (int i = 0; i < 256; i++) {
-		r_2_pix_alloc[i + 256] = format.RGBToColor(i, 0, 0);
-		g_2_pix_alloc[i + 256] = format.RGBToColor(0, i, 0);
-		b_2_pix_alloc[i + 256] = format.RGBToColor(0, 0, i);
-	}
+	if (scale == YUVToRGBManager::kScaleFull) {
+		// Set up entries 0-255 in rgb-to-pixel value tables.
+		for (int i = 0; i < 256; i++) {
+			r_2_pix_alloc[i + 256] = format.RGBToColor(i, 0, 0);
+			g_2_pix_alloc[i + 256] = format.RGBToColor(0, i, 0);
+			b_2_pix_alloc[i + 256] = format.RGBToColor(0, 0, i);
+		}
 
-	// Spread out the values we have to the rest of the array so that we do
-	// not need to check for overflow.
-	for (int i = 0; i < 256; i++) {
-		r_2_pix_alloc[i] = r_2_pix_alloc[256];
-		r_2_pix_alloc[i + 512] = r_2_pix_alloc[511];
-		g_2_pix_alloc[i] = g_2_pix_alloc[256];
-		g_2_pix_alloc[i + 512] = g_2_pix_alloc[511];
-		b_2_pix_alloc[i] = b_2_pix_alloc[256];
-		b_2_pix_alloc[i + 512] = b_2_pix_alloc[511];
-	}
-}
+		// Spread out the values we have to the rest of the array so that we do
+		// not need to check for overflow.
+		for (int i = 0; i < 256; i++) {
+			r_2_pix_alloc[i] = r_2_pix_alloc[256];
+			r_2_pix_alloc[i + 512] = r_2_pix_alloc[511];
+			g_2_pix_alloc[i] = g_2_pix_alloc[256];
+			g_2_pix_alloc[i + 512] = g_2_pix_alloc[511];
+			b_2_pix_alloc[i] = b_2_pix_alloc[256];
+			b_2_pix_alloc[i + 512] = b_2_pix_alloc[511];
+		}
+	} else {
+		// Set up entries 16-235 in rgb-to-pixel value tables
+		for (int i = 16; i < 236; i++) {
+			int scaledValue = (i - 16) * 255 / 219;
+			r_2_pix_alloc[i + 256] = format.RGBToColor(scaledValue, 0, 0);
+			g_2_pix_alloc[i + 256] = format.RGBToColor(0, scaledValue, 0);
+			b_2_pix_alloc[i + 256] = format.RGBToColor(0, 0, scaledValue);
+		}
+
+		// Spread out the values we have to the rest of the array so that we do
+		// not need to check for overflow. We have to do it here in two steps.
+		for (int i = 0; i < 256 + 16; i++) {
+			r_2_pix_alloc[i] = r_2_pix_alloc[256 + 16];
+			g_2_pix_alloc[i] = g_2_pix_alloc[256 + 16];
+			b_2_pix_alloc[i] = b_2_pix_alloc[256 + 16];
+		}
 
-YUVToRGBLookup::~YUVToRGBLookup() {
-	delete[] _rgbToPix;
+		for (int i = 256 + 236; i < 768; i++) {
+			r_2_pix_alloc[i] = r_2_pix_alloc[256 + 236 - 1];
+			g_2_pix_alloc[i] = g_2_pix_alloc[256 + 236 - 1];
+			b_2_pix_alloc[i] = b_2_pix_alloc[256 + 236 - 1];
+		}
+	}
 }
 
 YUVToRGBManager::YUVToRGBManager() {
@@ -156,13 +183,12 @@ YUVToRGBManager::~YUVToRGBManager() {
 	delete _lookup;
 }
 
-const YUVToRGBLookup *YUVToRGBManager::getLookup(Graphics::PixelFormat format) {
-	if (_lastFormat == format)
+const YUVToRGBLookup *YUVToRGBManager::getLookup(Graphics::PixelFormat format, YUVToRGBManager::LuminanceScale scale) {
+	if (_lookup && _lookup->getFormat() == format && _lookup->getScale() == scale)
 		return _lookup;
 
 	delete _lookup;
-	_lookup = new YUVToRGBLookup(format);
-	_lastFormat = format;
+	_lookup = new YUVToRGBLookup(format, scale);
 	return _lookup;
 }
 
@@ -177,7 +203,7 @@ void convertYUV444ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup
 	const int16 *Cr_g_tab = Cr_r_tab + 256;
 	const int16 *Cb_g_tab = Cr_g_tab + 256;
 	const int16 *Cb_b_tab = Cb_g_tab + 256;
-	const uint32 *rgbToPix = lookup->_rgbToPix;
+	const uint32 *rgbToPix = lookup->getRGBToPix();
 
 	for (int h = 0; h < yHeight; h++) {
 		for (int w = 0; w < yWidth; w++) {
@@ -201,13 +227,13 @@ void convertYUV444ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup
 	}
 }
 
-void YUVToRGBManager::convert444(Graphics::Surface *dst, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
+void YUVToRGBManager::convert444(Graphics::Surface *dst, YUVToRGBManager::LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
 	// Sanity checks
 	assert(dst && dst->pixels);
 	assert(dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4);
 	assert(ySrc && uSrc && vSrc);
 
-	const YUVToRGBLookup *lookup = getLookup(dst->format);
+	const YUVToRGBLookup *lookup = getLookup(dst->format, scale);
 
 	// Use a templated function to avoid an if check on every pixel
 	if (dst->format.bytesPerPixel == 2)
@@ -226,7 +252,7 @@ void convertYUV420ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup
 	const int16 *Cr_g_tab = Cr_r_tab + 256;
 	const int16 *Cb_g_tab = Cr_g_tab + 256;
 	const int16 *Cb_b_tab = Cb_g_tab + 256;
-	const uint32 *rgbToPix = lookup->_rgbToPix;
+	const uint32 *rgbToPix = lookup->getRGBToPix();
 
 	for (int h = 0; h < halfHeight; h++) {
 		for (int w = 0; w < halfWidth; w++) {
@@ -255,7 +281,7 @@ void convertYUV420ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup
 	}
 }
 
-void YUVToRGBManager::convert420(Graphics::Surface *dst, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
+void YUVToRGBManager::convert420(Graphics::Surface *dst, YUVToRGBManager::LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
 	// Sanity checks
 	assert(dst && dst->pixels);
 	assert(dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4);
@@ -263,7 +289,7 @@ void YUVToRGBManager::convert420(Graphics::Surface *dst, const byte *ySrc, const
 	assert((yWidth & 1) == 0);
 	assert((yHeight & 1) == 0);
 
-	const YUVToRGBLookup *lookup = getLookup(dst->format);
+	const YUVToRGBLookup *lookup = getLookup(dst->format, scale);
 
 	// Use a templated function to avoid an if check on every pixel
 	if (dst->format.bytesPerPixel == 2)
@@ -303,7 +329,7 @@ void convertYUV410ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup
 	const int16 *Cr_g_tab = Cr_r_tab + 256;
 	const int16 *Cb_g_tab = Cr_g_tab + 256;
 	const int16 *Cb_b_tab = Cb_g_tab + 256;
-	const uint32 *rgbToPix = lookup->_rgbToPix;
+	const uint32 *rgbToPix = lookup->getRGBToPix();
 
 	int quarterWidth = yWidth >> 2;
 
@@ -340,7 +366,7 @@ void convertYUV410ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup
 #undef DO_INTERPOLATION
 #undef DO_YUV410_PIXEL
 
-void YUVToRGBManager::convert410(Graphics::Surface *dst, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
+void YUVToRGBManager::convert410(Graphics::Surface *dst, YUVToRGBManager::LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
 	// Sanity checks
 	assert(dst && dst->pixels);
 	assert(dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4);
@@ -348,7 +374,7 @@ void YUVToRGBManager::convert410(Graphics::Surface *dst, const byte *ySrc, const
 	assert((yWidth & 3) == 0);
 	assert((yHeight & 3) == 0);
 
-	const YUVToRGBLookup *lookup = getLookup(dst->format);
+	const YUVToRGBLookup *lookup = getLookup(dst->format, scale);
 
 	// Use a templated function to avoid an if check on every pixel
 	if (dst->format.bytesPerPixel == 2)
diff --git a/graphics/yuv_to_rgb.h b/graphics/yuv_to_rgb.h
index 3af3fe8..68a0449 100644
--- a/graphics/yuv_to_rgb.h
+++ b/graphics/yuv_to_rgb.h
@@ -41,10 +41,17 @@ class YUVToRGBLookup;
 
 class YUVToRGBManager : public Common::Singleton<YUVToRGBManager> {
 public:
+	/** The scale of the luminance values */
+	enum LuminanceScale {
+		kScaleFull, /** Luminance values range from [0, 255] */
+		kScaleITU   /** Luminance values range from [16, 235], the range from ITU-R BT.601 */
+	};
+
 	/**
 	 * Convert a YUV444 image to an RGB surface
 	 *
 	 * @param dst     the destination surface
+	 * @param scale   the scale of the luminance values
 	 * @param ySrc    the source of the y component
 	 * @param uSrc    the source of the u component
 	 * @param vSrc    the source of the v component
@@ -53,12 +60,13 @@ public:
 	 * @param yPitch  the pitch of the y surface
 	 * @param uvPitch the pitch of the u and v surfaces
 	 */
-	void convert444(Graphics::Surface *dst, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch);
+	void convert444(Graphics::Surface *dst, LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch);
 
 	/**
 	 * Convert a YUV420 image to an RGB surface
 	 *
 	 * @param dst     the destination surface
+	 * @param scale   the scale of the luminance values
 	 * @param ySrc    the source of the y component
 	 * @param uSrc    the source of the u component
 	 * @param vSrc    the source of the v component
@@ -67,7 +75,7 @@ public:
 	 * @param yPitch  the pitch of the y surface
 	 * @param uvPitch the pitch of the u and v surfaces
 	 */
-	void convert420(Graphics::Surface *dst, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch);
+	void convert420(Graphics::Surface *dst, LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch);
 
 	/**
 	 * Convert a YUV410 image to an RGB surface	
@@ -78,6 +86,7 @@ public:
 	 * image (filled with 0x80). This is required in order to speed up this function.
 	 *
 	 * @param dst     the destination surface
+	 * @param scale   the scale of the luminance values
 	 * @param ySrc    the source of the y component
 	 * @param uSrc    the source of the u component
 	 * @param vSrc    the source of the v component
@@ -86,16 +95,15 @@ public:
 	 * @param yPitch  the pitch of the y surface
 	 * @param uvPitch the pitch of the u and v surfaces
 	 */
-	void convert410(Graphics::Surface *dst, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch);
+	void convert410(Graphics::Surface *dst, LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch);
 
 private:
 	friend class Common::Singleton<SingletonBaseType>;
 	YUVToRGBManager();
 	~YUVToRGBManager();
 
-	const YUVToRGBLookup *getLookup(Graphics::PixelFormat format);
+	const YUVToRGBLookup *getLookup(Graphics::PixelFormat format, LuminanceScale scale);
 
-	Graphics::PixelFormat _lastFormat;
 	YUVToRGBLookup *_lookup;
 	int16 _colorTab[4 * 256]; // 2048 bytes
 };
diff --git a/video/bink_decoder.cpp b/video/bink_decoder.cpp
index 65f0f6c..37e1262 100644
--- a/video/bink_decoder.cpp
+++ b/video/bink_decoder.cpp
@@ -348,7 +348,7 @@ void BinkDecoder::BinkVideoTrack::decodePacket(VideoFrame &frame) {
 	// The width used here is the surface-width, and not the video-width
 	// to allow for odd-sized videos.
 	assert(_curPlanes[0] && _curPlanes[1] && _curPlanes[2]);
-	YUVToRGBMan.convert420(&_surface, _curPlanes[0], _curPlanes[1], _curPlanes[2],
+	YUVToRGBMan.convert420(&_surface, Graphics::YUVToRGBManager::kScaleITU, _curPlanes[0], _curPlanes[1], _curPlanes[2],
 			_surfaceWidth, _surfaceHeight, _surfaceWidth, _surfaceWidth >> 1);
 
 	// And swap the planes with the reference planes
diff --git a/video/codecs/svq1.cpp b/video/codecs/svq1.cpp
index 41bd1dc..5f0f76f 100644
--- a/video/codecs/svq1.cpp
+++ b/video/codecs/svq1.cpp
@@ -256,7 +256,7 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st
 		_surface->h = _height;
 	}
 
-	YUVToRGBMan.convert410(_surface, current[0], current[1], current[2], yWidth, yHeight, yWidth, uvWidth);
+	YUVToRGBMan.convert410(_surface, Graphics::YUVToRGBManager::kScaleFull, current[0], current[1], current[2], yWidth, yHeight, yWidth, uvWidth);
 
 	// Store the current surfaces for later and free the old ones
 	for (int i = 0; i < 3; i++) {
diff --git a/video/psx_decoder.cpp b/video/psx_decoder.cpp
index 7cdc53d..f19802f 100644
--- a/video/psx_decoder.cpp
+++ b/video/psx_decoder.cpp
@@ -483,7 +483,7 @@ void PSXStreamDecoder::PSXVideoTrack::decodeFrame(Common::SeekableReadStream *fr
 			decodeMacroBlock(&bits, mbX, mbY, scale, version);
 
 	// Output data onto the frame
-	YUVToRGBMan.convert420(_surface, _yBuffer, _cbBuffer, _crBuffer, _surface->w, _surface->h, _macroBlocksW * 16, _macroBlocksW * 8);
+	YUVToRGBMan.convert420(_surface, Graphics::YUVToRGBManager::kScaleFull, _yBuffer, _cbBuffer, _crBuffer, _surface->w, _surface->h, _macroBlocksW * 16, _macroBlocksW * 8);
 
 	_curFrame++;
 
diff --git a/video/theora_decoder.cpp b/video/theora_decoder.cpp
index 8b57932..bf953b0 100644
--- a/video/theora_decoder.cpp
+++ b/video/theora_decoder.cpp
@@ -328,7 +328,7 @@ void TheoraDecoder::TheoraVideoTrack::translateYUVtoRGBA(th_ycbcr_buffer &YUVBuf
 	assert(YUVBuffer[kBufferU].height == YUVBuffer[kBufferY].height >> 1);
 	assert(YUVBuffer[kBufferV].height == YUVBuffer[kBufferY].height >> 1);
 
-	YUVToRGBMan.convert420(&_surface, YUVBuffer[kBufferY].data, YUVBuffer[kBufferU].data, YUVBuffer[kBufferV].data, YUVBuffer[kBufferY].width, YUVBuffer[kBufferY].height, YUVBuffer[kBufferY].stride, YUVBuffer[kBufferU].stride);
+	YUVToRGBMan.convert420(&_surface, Graphics::YUVToRGBManager::kScaleITU, YUVBuffer[kBufferY].data, YUVBuffer[kBufferU].data, YUVBuffer[kBufferV].data, YUVBuffer[kBufferY].width, YUVBuffer[kBufferY].height, YUVBuffer[kBufferY].stride, YUVBuffer[kBufferU].stride);
 }
 
 static vorbis_info *info = 0;






More information about the Scummvm-git-logs mailing list