aboutsummaryrefslogtreecommitdiff
path: root/graphics/decoders
diff options
context:
space:
mode:
authorJohannes Schickel2013-08-12 00:53:34 +0200
committerJohannes Schickel2013-09-16 19:54:19 +0200
commit4809294b43e1c43957874bdfcdadfc299fd7ace4 (patch)
treea4f314e1b8011cdbc654ab7cfe2ee874350aae75 /graphics/decoders
parentac66cc921904387518f2e0b2a14670e9598defe4 (diff)
downloadscummvm-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.cpp88
-rw-r--r--graphics/decoders/jpeg.h53
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