diff options
author | Johannes Schickel | 2013-08-12 00:53:34 +0200 |
---|---|---|
committer | Johannes Schickel | 2013-09-16 19:54:19 +0200 |
commit | 4809294b43e1c43957874bdfcdadfc299fd7ace4 (patch) | |
tree | a4f314e1b8011cdbc654ab7cfe2ee874350aae75 /graphics/decoders | |
parent | ac66cc921904387518f2e0b2a14670e9598defe4 (diff) | |
download | scummvm-rg350-4809294b43e1c43957874bdfcdadfc299fd7ace4.tar.gz scummvm-rg350-4809294b43e1c43957874bdfcdadfc299fd7ace4.tar.bz2 scummvm-rg350-4809294b43e1c43957874bdfcdadfc299fd7ace4.zip |
GRAPHICS: Make JPEGDecoder request RGB output from libjpeg by default.
This fixes loading of JPEG files which contain RGB color space instead of YUV.
It is a pretty odd extension of JPEG files by Adobe which is indicated by this:
http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html#Adobe
To still support Groovie's need for YUV data I added some possibility to
request direct YUV output.
Diffstat (limited to 'graphics/decoders')
-rw-r--r-- | graphics/decoders/jpeg.cpp | 88 | ||||
-rw-r--r-- | graphics/decoders/jpeg.h | 53 |
2 files changed, 90 insertions, 51 deletions
diff --git a/graphics/decoders/jpeg.cpp b/graphics/decoders/jpeg.cpp index 891542c415..ba6292bbbd 100644 --- a/graphics/decoders/jpeg.cpp +++ b/graphics/decoders/jpeg.cpp @@ -25,7 +25,6 @@ #define FORBIDDEN_SYMBOL_ALLOW_ALL #include "graphics/pixelformat.h" -#include "graphics/yuv_to_rgb.h" #include "graphics/decoders/jpeg.h" #include "common/debug.h" @@ -45,7 +44,7 @@ extern "C" { namespace Graphics { -JPEGDecoder::JPEGDecoder() : ImageDecoder(), _rgbSurface(nullptr) { +JPEGDecoder::JPEGDecoder() : ImageDecoder(), _surface(), _colorSpace(kColorSpaceRGBA) { } JPEGDecoder::~JPEGDecoder() { @@ -53,31 +52,11 @@ JPEGDecoder::~JPEGDecoder() { } const Surface *JPEGDecoder::getSurface() const { - // Make sure we have loaded data - if (!_yComponent.getPixels()) - return 0; - - if (_rgbSurface) - return _rgbSurface; - - // Create an RGBA8888 surface - _rgbSurface = new Graphics::Surface(); - _rgbSurface->create(_yComponent.w, _yComponent.h, Graphics::PixelFormat(4, 8, 8, 8, 0, 24, 16, 8, 0)); - - YUVToRGBMan.convert444(_rgbSurface, Graphics::YUVToRGBManager::kScaleFull, (const byte *)_yComponent.getPixels(), (const byte *)_uComponent.getPixels(), (const byte *)_vComponent.getPixels(), _yComponent.w, _yComponent.h, _yComponent.pitch, _uComponent.pitch); - - return _rgbSurface; + return &_surface; } void JPEGDecoder::destroy() { - if (_rgbSurface) { - _rgbSurface->free(); - delete _rgbSurface; - } - - _yComponent.free(); - _uComponent.free(); - _vComponent.free(); + _surface.free(); } #ifdef USE_JPEG @@ -206,16 +185,33 @@ bool JPEGDecoder::loadStream(Common::SeekableReadStream &stream) { // Read the file header jpeg_read_header(&cinfo, TRUE); - // We request YUV output because Groovie requires it - cinfo.out_color_space = JCS_YCbCr; + // We can request YUV output because Groovie requires it + switch (_colorSpace) { + case kColorSpaceRGBA: + cinfo.out_color_space = JCS_RGB; + break; + + case kColorSpaceYUV: + cinfo.out_color_space = JCS_YCbCr; + break; + } // Actually start decompressing the image jpeg_start_decompress(&cinfo); - // Allocate buffers for the YUV components - _yComponent.create(cinfo.output_width, cinfo.output_height, Graphics::PixelFormat::createFormatCLUT8()); - _uComponent.create(cinfo.output_width, cinfo.output_height, Graphics::PixelFormat::createFormatCLUT8()); - _vComponent.create(cinfo.output_width, cinfo.output_height, Graphics::PixelFormat::createFormatCLUT8()); + // 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)); + break; + + case kColorSpaceYUV: + // We use YUV with 3 bytes per pixel otherwise. + // This is pretty ugly since our PixelFormat cannot express YUV... + _surface.create(cinfo.output_width, cinfo.output_height, Graphics::PixelFormat(3, 0, 0, 0, 0, 0, 0, 0, 0)); + break; + } // Allocate buffer for one scanline JDIMENSION pitch = cinfo.output_width * cinfo.output_components; @@ -223,17 +219,35 @@ bool JPEGDecoder::loadStream(Common::SeekableReadStream &stream) { // Go through the image data scanline by scanline while (cinfo.output_scanline < cinfo.output_height) { - byte *yPtr = (byte *)_yComponent.getBasePtr(0, cinfo.output_scanline); - byte *uPtr = (byte *)_uComponent.getBasePtr(0, cinfo.output_scanline); - byte *vPtr = (byte *)_vComponent.getBasePtr(0, cinfo.output_scanline); + byte *dst = (byte *)_surface.getBasePtr(0, cinfo.output_scanline); jpeg_read_scanlines(&cinfo, buffer, 1); const byte *src = buffer[0]; - for (int remaining = cinfo.output_width; remaining > 0; --remaining) { - *yPtr++ = *src++; - *uPtr++ = *src++; - *vPtr++ = *src++; + 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, _surface.pitch); + break; } } diff --git a/graphics/decoders/jpeg.h b/graphics/decoders/jpeg.h index 53e7bb10c8..8460bc2698 100644 --- a/graphics/decoders/jpeg.h +++ b/graphics/decoders/jpeg.h @@ -46,23 +46,48 @@ public: ~JPEGDecoder(); // ImageDecoder API - void destroy(); - bool loadStream(Common::SeekableReadStream &str); - const Surface *getSurface() const; + virtual void destroy(); + virtual bool loadStream(Common::SeekableReadStream &str); + virtual const Surface *getSurface() const; - const Surface &getYComponent() const { return _yComponent; } - const Surface &getUComponent() const { return _uComponent; } - const Surface &getVComponent() const { return _vComponent; } + // Special API for JPEG + enum ColorSpace { + /** + * Output 32bit RGBA data. + * + * This is the default output. + */ + kColorSpaceRGBA, -private: - // mutable so that we can convert to RGB only during - // a getSurface() call while still upholding the - // const requirement in other ImageDecoders - mutable Graphics::Surface *_rgbSurface; + /** + * Output (interleaved) YUV data. + * + * Be aware that some images cannot be output in YUV mode. + * These are (non-standard) JPEG images which are in RGB colorspace. + * + * The resulting Surface will have a PixelFormat with 3 bytes per + * pixel and the remaining entries are completely zeroed. This works + * around the fact that PixelFormat can only describe RGB formats. + * + * You should only use this when you are really aware of what you are + * doing! + */ + kColorSpaceYUV + }; + + /** + * 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. + * + * @param outSpace The color space to output. + */ + void setOutputColorSpace(ColorSpace outSpace) { _colorSpace = outSpace; } - Graphics::Surface _yComponent; - Graphics::Surface _uComponent; - Graphics::Surface _vComponent; +private: + Graphics::Surface _surface; + ColorSpace _colorSpace; }; } // End of Graphics namespace |