diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2014-04-18 20:46:34 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2014-04-18 20:53:01 +0200 |
commit | 1139d618b8bc6ab823a96184bd0f0257980aad24 (patch) | |
tree | 763931577dbadbc3e6853950a3df099b1f69a4f4 /vcl | |
parent | 8afabd394214bb7c772c88b08ec3cadb56771cce (diff) |
handle strange brightness+contrast adjustment from msoffice (fdo#38410)
LO uses basically the formula "newpixel=(oldpixel-128)*contrast+128+brightness",
i.e. contrast is applied first. It looks like there's no "oficial" formula for this,
so a formula that applies brightness first would be ok too. MSO for some weird reason
apparently uses a formula that applies half of brightness before contrast and
half afterwards (insert funny political correctness or compromise joke here).
While the result is the same like with the LO formula if only either brightness
or contrast is adjusted, the result is different if both are involved. Just modify
the image using the MSO algorithm if this is the case.
Change-Id: I55fe8f395832685b90f024cf2f58b0797c1ba588
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/source/gdi/bitmap3.cxx | 28 | ||||
-rw-r--r-- | vcl/source/gdi/bitmapex.cxx | 4 | ||||
-rw-r--r-- | vcl/source/gdi/gdimtf.cxx | 25 |
3 files changed, 41 insertions, 16 deletions
diff --git a/vcl/source/gdi/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx index 51221ee5873f..5da113f6f10b 100644 --- a/vcl/source/gdi/bitmap3.cxx +++ b/vcl/source/gdi/bitmap3.cxx @@ -3215,7 +3215,7 @@ bool Bitmap::Vectorize( GDIMetaFile& rMtf, sal_uInt8 cReduce, sal_uLong nFlags, bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent, short nChannelRPercent, short nChannelGPercent, short nChannelBPercent, - double fGamma, bool bInvert ) + double fGamma, bool bInvert, bool msoBrightness ) { bool bRet = false; @@ -3246,8 +3246,11 @@ bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent, else fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0; - // total offset = luminance offset + contrast offset - fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0; + if(!msoBrightness) + // total offset = luminance offset + contrast offset + fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0; + else + fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55; // channel offset = channel offset + total offset fROff = nChannelRPercent * 2.55 + fOff; @@ -3261,10 +3264,21 @@ bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent, // create mapping table for( long nX = 0L; nX < 256L; nX++ ) { - cMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L ); - cMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L ); - cMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L ); - + if(!msoBrightness) + { + cMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L ); + cMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L ); + cMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L ); + } + else + { + // LO simply uses (in a somewhat optimized form) "newcolor = (oldcolor-128)*contrast+brightness+128" + // as the formula, i.e. contrast first, brightness afterwards. MSOffice, for whatever weird reason, + // use neither first, but apparently it applies half of brightness before contrast and half afterwards. + cMapR[ nX ] = (sal_uInt8) MinMax( FRound( (nX+fROff/2-128) * fM + 128 + fROff/2 ), 0L, 255L ); + cMapG[ nX ] = (sal_uInt8) MinMax( FRound( (nX+fGOff/2-128) * fM + 128 + fGOff/2 ), 0L, 255L ); + cMapB[ nX ] = (sal_uInt8) MinMax( FRound( (nX+fBOff/2-128) * fM + 128 + fBOff/2 ), 0L, 255L ); + } if( bGamma ) { cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma ); diff --git a/vcl/source/gdi/bitmapex.cxx b/vcl/source/gdi/bitmapex.cxx index 0e41be103957..8a5cd0970c85 100644 --- a/vcl/source/gdi/bitmapex.cxx +++ b/vcl/source/gdi/bitmapex.cxx @@ -629,11 +629,11 @@ bool BitmapEx::Replace( const Color* pSearchColors, const Color* pReplaceColors, bool BitmapEx::Adjust( short nLuminancePercent, short nContrastPercent, short nChannelRPercent, short nChannelGPercent, short nChannelBPercent, - double fGamma, bool bInvert ) + double fGamma, bool bInvert, bool msoBrightness ) { return( !!aBitmap ? aBitmap.Adjust( nLuminancePercent, nContrastPercent, nChannelRPercent, nChannelGPercent, nChannelBPercent, - fGamma, bInvert ) : false ); + fGamma, bInvert, msoBrightness ) : false ); } bool BitmapEx::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress ) diff --git a/vcl/source/gdi/gdimtf.cxx b/vcl/source/gdi/gdimtf.cxx index 7aee9fa40665..7107023a2f58 100644 --- a/vcl/source/gdi/gdimtf.cxx +++ b/vcl/source/gdi/gdimtf.cxx @@ -2176,7 +2176,7 @@ void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol, const void* pCol void GDIMetaFile::Adjust( short nLuminancePercent, short nContrastPercent, short nChannelRPercent, short nChannelGPercent, - short nChannelBPercent, double fGamma, bool bInvert ) + short nChannelBPercent, double fGamma, bool bInvert, bool msoBrightness ) { // nothing to do? => return quickly if( nLuminancePercent || nContrastPercent || @@ -2197,8 +2197,11 @@ void GDIMetaFile::Adjust( short nLuminancePercent, short nContrastPercent, else fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0; - // total offset = luminance offset + contrast offset - fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0; + if(!msoBrightness) + // total offset = luminance offset + contrast offset + fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0; + else + fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55; // channel offset = channel offset + total offset fROff = nChannelRPercent * 2.55 + fOff; @@ -2212,10 +2215,18 @@ void GDIMetaFile::Adjust( short nLuminancePercent, short nContrastPercent, // create mapping table for( long nX = 0L; nX < 256L; nX++ ) { - aColParam.pMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L ); - aColParam.pMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L ); - aColParam.pMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L ); - + if(!msoBrightness) + { + aColParam.pMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L ); + aColParam.pMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L ); + aColParam.pMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L ); + } + else + { + aColParam.pMapR[ nX ] = (sal_uInt8) MinMax( FRound( (nX+fROff/2-128) * fM + 128 + fROff/2 ), 0L, 255L ); + aColParam.pMapG[ nX ] = (sal_uInt8) MinMax( FRound( (nX+fGOff/2-128) * fM + 128 + fGOff/2 ), 0L, 255L ); + aColParam.pMapB[ nX ] = (sal_uInt8) MinMax( FRound( (nX+fBOff/2-128) * fM + 128 + fBOff/2 ), 0L, 255L ); + } if( bGamma ) { aColParam.pMapR[ nX ] = GAMMA( aColParam.pMapR[ nX ], fGamma ); |