aboutsummaryrefslogtreecommitdiff
path: root/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'graphics')
-rw-r--r--graphics/decoders/jpeg.cpp2
-rw-r--r--graphics/yuv_to_rgb.cpp100
-rw-r--r--graphics/yuv_to_rgb.h18
3 files changed, 77 insertions, 43 deletions
diff --git a/graphics/decoders/jpeg.cpp b/graphics/decoders/jpeg.cpp
index 77ca316c6d..748275b84b 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 1afd0d295b..6043315a13 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 3af3fe87e4..68a0449d2c 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
};