diff options
| -rw-r--r-- | engines/glk/picture.cpp | 1 | ||||
| -rw-r--r-- | engines/groovie/roq.cpp | 5 | ||||
| -rw-r--r-- | engines/titanic/support/image_decoders.cpp | 13 | ||||
| -rw-r--r-- | graphics/yuv_to_rgb.h | 3 | ||||
| -rw-r--r-- | image/codecs/mjpeg.cpp | 6 | ||||
| -rw-r--r-- | image/jpeg.cpp | 114 | ||||
| -rw-r--r-- | image/jpeg.h | 16 | 
7 files changed, 108 insertions, 50 deletions
| diff --git a/engines/glk/picture.cpp b/engines/glk/picture.cpp index a47d8bf3d6..306444449c 100644 --- a/engines/glk/picture.cpp +++ b/engines/glk/picture.cpp @@ -125,6 +125,7 @@ Picture *Pictures::load(uint32 id) {  		palette = png.getPalette();  		palCount = png.getPaletteColorCount();  	} else if (f.open(Common::String::format("pic%u.jpg", id))) { +		jpg.setOutputPixelFormat(g_system->getScreenFormat());  		jpg.loadStream(f);  		img = jpg.getSurface();  	} else if (f.open(Common::String::format("pic%u.raw", id))) { diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp index c1b6c44c4d..2e9a394c53 100644 --- a/engines/groovie/roq.cpp +++ b/engines/groovie/roq.cpp @@ -470,6 +470,7 @@ bool ROQPlayer::processBlockStill(ROQBlockHeader &blockHeader) {  	debugC(5, kDebugVideo, "Groovie::ROQ: Processing still (JPEG) block");  	Image::JPEGDecoder jpg; +	jpg.setOutputPixelFormat(_vm->_pixelFormat);  	uint32 startPos = _file->pos();  	Common::SeekableSubReadStream subStream(_file, startPos, startPos + blockHeader.size, DisposeAfterUse::NO); @@ -478,7 +479,9 @@ bool ROQPlayer::processBlockStill(ROQBlockHeader &blockHeader) {  	const Graphics::Surface *srcSurf = jpg.getSurface();  	_currBuf->free();  	delete _currBuf; -	_currBuf = srcSurf->convertTo(_vm->_pixelFormat); + +	_currBuf = new Graphics::Surface(); +	_currBuf->copyFrom(*srcSurf);  	_file->seek(startPos + blockHeader.size);  	return true; diff --git a/engines/titanic/support/image_decoders.cpp b/engines/titanic/support/image_decoders.cpp index 3819b85116..7c902b2c6d 100644 --- a/engines/titanic/support/image_decoders.cpp +++ b/engines/titanic/support/image_decoders.cpp @@ -20,6 +20,7 @@   *   */ +#include "common/system.h"  #include "titanic/support/image_decoders.h"  namespace Titanic { @@ -29,7 +30,8 @@ void CJPEGDecode::decode(OSVideoSurface &surface, const CString &name) {  	StdCWadFile file;  	file.open(name); -	// Use the ScucmmVM deoder to decode it +	// Use the ScummVM decoder to decode it +	setOutputPixelFormat(g_system->getScreenFormat());  	loadStream(*file.readStream());  	const Graphics::Surface *srcSurf = getSurface(); @@ -38,15 +40,14 @@ void CJPEGDecode::decode(OSVideoSurface &surface, const CString &name) {  			|| surface.getHeight() != srcSurf->h)  		surface.recreate(srcSurf->w, srcSurf->h, 16); -	// Convert the decoded surface to the correct pixel format, and then copy it over +	// Copy the decoded surface  	surface.lock(); -	Graphics::Surface *convertedSurface = srcSurf->convertTo(surface._rawSurface->format); -	Common::copy((byte *)convertedSurface->getPixels(), (byte *)convertedSurface->getPixels() + +	assert(srcSurf->format == surface._rawSurface->format); + +	Common::copy((const byte *)srcSurf->getPixels(), (const byte *)srcSurf->getPixels() +  		surface.getPitch() * surface.getHeight(), (byte *)surface._rawSurface->getPixels()); -	convertedSurface->free(); -	delete convertedSurface;  	surface.unlock();  } diff --git a/graphics/yuv_to_rgb.h b/graphics/yuv_to_rgb.h index a1e61ec705..3d11f35048 100644 --- a/graphics/yuv_to_rgb.h +++ b/graphics/yuv_to_rgb.h @@ -24,9 +24,6 @@   * @file   * YUV to RGB conversion.   * - * Used in graphics: - * - JPEGDecoder - *   * Used in video:   * - BinkDecoder   * - Indeo3Decoder diff --git a/image/codecs/mjpeg.cpp b/image/codecs/mjpeg.cpp index 6e7faf1045..c5f815342b 100644 --- a/image/codecs/mjpeg.cpp +++ b/image/codecs/mjpeg.cpp @@ -200,6 +200,7 @@ const Graphics::Surface *MJPEGDecoder::decodeFrame(Common::SeekableReadStream &s  	Common::MemoryReadStream convertedStream(data, outputSize, DisposeAfterUse::YES);  	JPEGDecoder jpeg; +	jpeg.setOutputPixelFormat(_pixelFormat);  	if (!jpeg.loadStream(convertedStream)) {  		warning("Failed to decode MJPEG frame"); @@ -211,7 +212,10 @@ const Graphics::Surface *MJPEGDecoder::decodeFrame(Common::SeekableReadStream &s  		delete _surface;  	} -	_surface = jpeg.getSurface()->convertTo(_pixelFormat); +	_surface = new Graphics::Surface(); +	_surface->copyFrom(*jpeg.getSurface()); + +	assert(_surface->format == _pixelFormat);  	return _surface;  } diff --git a/image/jpeg.cpp b/image/jpeg.cpp index 1ce45f2539..5cc348fdfe 100644 --- a/image/jpeg.cpp +++ b/image/jpeg.cpp @@ -30,6 +30,7 @@  #include "common/endian.h"  #include "common/stream.h"  #include "common/textconsole.h" +#include "common/util.h"  #include "graphics/pixelformat.h"  #ifdef USE_JPEG @@ -44,13 +45,24 @@ extern "C" {  namespace Image { -JPEGDecoder::JPEGDecoder() : _surface(), _colorSpace(kColorSpaceRGBA) { +JPEGDecoder::JPEGDecoder() : +		_surface(), +		_colorSpace(kColorSpaceRGB), +		_requestedPixelFormat(getByteOrderRgbPixelFormat()) {  }  JPEGDecoder::~JPEGDecoder() {  	destroy();  } +Graphics::PixelFormat JPEGDecoder::getByteOrderRgbPixelFormat() const { +#ifdef SCUMM_BIG_ENDIAN +	return Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0); +#else +	return Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0); +#endif +} +  const Graphics::Surface *JPEGDecoder::getSurface() const {  	return &_surface;  } @@ -171,6 +183,44 @@ void outputMessage(j_common_ptr cinfo) {  	debug(3, "libjpeg: %s", buffer);  } +J_COLOR_SPACE fromScummvmPixelFormat(const Graphics::PixelFormat &format) { +	struct PixelFormatMapping { +		Graphics::PixelFormat pixelFormat; +		J_COLOR_SPACE bigEndianColorSpace; +		J_COLOR_SPACE littleEndianColorSpace; +	}; + +	static const PixelFormatMapping mappings[] = { +#ifdef JCS_EXTENSIONS +		{ Graphics::PixelFormat(4, 8, 8, 8, 0, 24, 16,  8,  0), JCS_EXT_RGBX, JCS_EXT_XBGR }, +		{ Graphics::PixelFormat(4, 8, 8, 8, 0,  0,  8, 16, 24), JCS_EXT_XBGR, JCS_EXT_RGBX }, +		{ Graphics::PixelFormat(4, 8, 8, 8, 0, 16,  8,  0, 24), JCS_EXT_XRGB, JCS_EXT_BGRX }, +		{ Graphics::PixelFormat(4, 8, 8, 8, 0,  8, 16, 24,  0), JCS_EXT_BGRX, JCS_EXT_XRGB }, +		{ Graphics::PixelFormat(3, 8, 8, 8, 0, 16,  8,  0,  0), JCS_EXT_RGB,  JCS_EXT_BGR  }, +		{ Graphics::PixelFormat(3, 8, 8, 8, 0,  0,  8, 16,  0), JCS_EXT_BGR,  JCS_EXT_RGB  }, +#endif +#ifdef JCS_ALPHA_EXTENSIONS +		{ Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16,  8,  0), JCS_EXT_RGBA, JCS_EXT_ABGR }, +		{ Graphics::PixelFormat(4, 8, 8, 8, 8,  0,  8, 16, 24), JCS_EXT_ABGR, JCS_EXT_RGBA }, +		{ Graphics::PixelFormat(4, 8, 8, 8, 8, 16,  8,  0, 24), JCS_EXT_ARGB, JCS_EXT_BGRA }, +		{ Graphics::PixelFormat(4, 8, 8, 8, 8,  8, 16, 24,  0), JCS_EXT_BGRA, JCS_EXT_ARGB }, +#endif +		{ Graphics::PixelFormat(2, 5, 6, 5, 0, 11,  5,  0,  0), JCS_RGB565,   JCS_RGB565   } +	}; + +	for (uint i = 0; i < ARRAYSIZE(mappings); i++) { +		if (mappings[i].pixelFormat == format) { +#ifdef SCUMM_BIG_ENDIAN +			return mappings[i].bigEndianColorSpace; +#else +			return mappings[i].littleEndianColorSpace; +#endif +		} +	} + +	return JCS_UNKNOWN; +} +  } // End of anonymous namespace  #endif @@ -198,10 +248,19 @@ bool JPEGDecoder::loadStream(Common::SeekableReadStream &stream) {  	// We can request YUV output because Groovie requires it  	switch (_colorSpace) { -	case kColorSpaceRGBA: -		cinfo.out_color_space = JCS_RGB; -		break; +	case kColorSpaceRGB: { +		J_COLOR_SPACE colorSpace = fromScummvmPixelFormat(_requestedPixelFormat); + +		if (colorSpace == JCS_UNKNOWN) { +			// When libjpeg-turbo is not available or an unhandled pixel +			// format was requested, ask libjpeg to decode to byte order RGB +			// as it's always available. +			colorSpace = JCS_RGB; +		} +		cinfo.out_color_space = colorSpace; +		break; +	}  	case kColorSpaceYUV:  		cinfo.out_color_space = JCS_YCbCr;  		break; @@ -212,11 +271,16 @@ bool JPEGDecoder::loadStream(Common::SeekableReadStream &stream) {  	// Allocate buffers for the output data  	switch (_colorSpace) { -	case kColorSpaceRGBA: -		// We use RGBA8888 in this scenario -		_surface.create(cinfo.output_width, cinfo.output_height, Graphics::PixelFormat(4, 8, 8, 8, 0, 24, 16, 8, 0)); +	case kColorSpaceRGB: { +		Graphics::PixelFormat outputPixelFormat; +		if (cinfo.out_color_space == JCS_RGB) { +			outputPixelFormat = getByteOrderRgbPixelFormat(); +		} else { +			outputPixelFormat = _requestedPixelFormat; +		} +		_surface.create(cinfo.output_width, cinfo.output_height, outputPixelFormat);  		break; - +	}  	case kColorSpaceYUV:  		// We use YUV with 3 bytes per pixel otherwise.  		// This is pretty ugly since our PixelFormat cannot express YUV... @@ -225,8 +289,7 @@ bool JPEGDecoder::loadStream(Common::SeekableReadStream &stream) {  	}  	// Allocate buffer for one scanline -	assert(cinfo.output_components == 3); -	JDIMENSION pitch = cinfo.output_width * cinfo.output_components; +	JDIMENSION pitch = cinfo.output_width * _surface.format.bytesPerPixel;  	assert(_surface.pitch >= pitch);  	JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, pitch, 1); @@ -236,38 +299,17 @@ bool JPEGDecoder::loadStream(Common::SeekableReadStream &stream) {  		jpeg_read_scanlines(&cinfo, buffer, 1); -		const byte *src = buffer[0]; -		switch (_colorSpace) { -		case kColorSpaceRGBA: { -			for (int remaining = cinfo.output_width; remaining > 0; --remaining) { -				byte r = *src++; -				byte g = *src++; -				byte b = *src++; -				// We need to insert a alpha value of 255 (opaque) here. -#ifdef SCUMM_BIG_ENDIAN -				*dst++ = r; -				*dst++ = g; -				*dst++ = b; -				*dst++ = 0xFF; -#else -				*dst++ = 0xFF; -				*dst++ = b; -				*dst++ = g; -				*dst++ = r; -#endif -			} -			} break; - -		case kColorSpaceYUV: -			memcpy(dst, src, pitch); -			break; -		} +		memcpy(dst, buffer[0], pitch);  	}  	// We are done with decompressing, thus free all the data  	jpeg_finish_decompress(&cinfo);  	jpeg_destroy_decompress(&cinfo); +	if (_colorSpace == kColorSpaceRGB && _surface.format != _requestedPixelFormat) { +		_surface.convertToInPlace(_requestedPixelFormat); // Slow path +	} +  	return true;  #else  	return false; diff --git a/image/jpeg.h b/image/jpeg.h index ac0d22d129..08b5c01dc4 100644 --- a/image/jpeg.h +++ b/image/jpeg.h @@ -60,11 +60,11 @@ public:  	// Special API for JPEG  	enum ColorSpace {  		/** -		 * Output 32bit RGBA data. +		 * Output RGB data in the pixel format specified using `setOutputPixelFormat`.  		 *  		 * This is the default output.  		 */ -		kColorSpaceRGBA, +		kColorSpaceRGB,  		/**  		 * Output (interleaved) YUV data. @@ -86,15 +86,25 @@ public:  	 * Request the output color space. This can be used to obtain raw YUV  	 * data from the JPEG file. But this might not work for all files!  	 * -	 * The decoder itself defaults to RGBA. +	 * The decoder itself defaults to RGB.  	 *  	 * @param outSpace The color space to output.  	 */  	void setOutputColorSpace(ColorSpace outSpace) { _colorSpace = outSpace; } +	/** +	 * Request the output pixel format. The JPEG decoder provides high performance +	 * color conversion routines for some pixel formats. This setting allows to use +	 * them and avoid costly subsequent color conversion. +	 */ +	void setOutputPixelFormat(const Graphics::PixelFormat &format) { _requestedPixelFormat = format; } +  private:  	Graphics::Surface _surface;  	ColorSpace _colorSpace; +	Graphics::PixelFormat _requestedPixelFormat; + +	Graphics::PixelFormat getByteOrderRgbPixelFormat() const;  };  } // End of namespace Image | 
