summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2014-04-18 20:46:34 +0200
committerLuboš Luňák <l.lunak@collabora.com>2014-04-18 21:53:11 +0200
commitb5fd2f9ff7c869065d424aa3b0632549480eb5b6 (patch)
tree20ac65ad6072178c0b7ca6fc91bbb79f7e36c7e4
parent3750025d3290fd4db6b18dcc33c9c077b05af524 (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. Conflicts: filter/source/msfilter/msdffimp.cxx include/vcl/bitmap.hxx include/vcl/bitmapex.hxx include/vcl/gdimtf.hxx vcl/source/gdi/bitmap3.cxx vcl/source/gdi/bitmapex.cxx vcl/source/gdi/gdimtf.cxx Change-Id: I55fe8f395832685b90f024cf2f58b0797c1ba588
-rw-r--r--filter/source/msfilter/msdffimp.cxx11
-rw-r--r--include/vcl/bitmap.hxx6
-rw-r--r--include/vcl/bitmapex.hxx7
-rw-r--r--include/vcl/gdimtf.hxx2
-rw-r--r--vcl/source/gdi/bitmap3.cxx28
-rw-r--r--vcl/source/gdi/bitmapex.cxx4
-rw-r--r--vcl/source/gdi/gdimtf.cxx25
7 files changed, 61 insertions, 22 deletions
diff --git a/filter/source/msfilter/msdffimp.cxx b/filter/source/msfilter/msdffimp.cxx
index 09f15c05e1a4..f37a5551151b 100644
--- a/filter/source/msfilter/msdffimp.cxx
+++ b/filter/source/msfilter/msdffimp.cxx
@@ -3816,7 +3816,12 @@ SdrObject* SvxMSDffManager::ImportGraphic( SvStream& rSt, SfxItemSet& rSet, cons
if ( nContrast || nBrightness || ( nGamma != 0x10000 ) || ( eDrawMode != GRAPHICDRAWMODE_STANDARD ) )
{
- if ( ( rObjData.nSpFlags & SP_FOLESHAPE ) == 0 )
+ // MSO uses a different algorithm for contrast+brightness, LO applies contrast before brightness,
+ // while MSO apparently applies half of brightness before contrast and half after. So if only
+ // contrast or brightness need to be altered, the result is the same, but if both are involved,
+ // there's no way to map that, so just force a conversion of the image.
+ bool needsConversion = nContrast != 0 && nBrightness != 0;
+ if ( ( rObjData.nSpFlags & SP_FOLESHAPE ) == 0 && !needsConversion )
{
if ( nBrightness )
rSet.Put( SdrGrafLuminanceItem( nBrightness ) );
@@ -3841,7 +3846,7 @@ SdrObject* SvxMSDffManager::ImportGraphic( SvStream& rSt, SfxItemSet& rSet, cons
{
BitmapEx aBitmapEx( aGraf.GetBitmapEx() );
if ( nBrightness || nContrast || ( nGamma != 0x10000 ) )
- aBitmapEx.Adjust( nBrightness, (sal_Int16)nContrast, 0, 0, 0, (double)nGamma / 0x10000, sal_False );
+ aBitmapEx.Adjust( nBrightness, (sal_Int16)nContrast, 0, 0, 0, (double)nGamma / 0x10000, false, true );
if ( eDrawMode == GRAPHICDRAWMODE_GREYS )
aBitmapEx.Convert( BMP_CONVERSION_8BIT_GREYS );
else if ( eDrawMode == GRAPHICDRAWMODE_MONO )
@@ -3855,7 +3860,7 @@ SdrObject* SvxMSDffManager::ImportGraphic( SvStream& rSt, SfxItemSet& rSet, cons
{
GDIMetaFile aGdiMetaFile( aGraf.GetGDIMetaFile() );
if ( nBrightness || nContrast || ( nGamma != 0x10000 ) )
- aGdiMetaFile.Adjust( nBrightness, (sal_Int16)nContrast, 0, 0, 0, (double)nGamma / 0x10000, sal_False );
+ aGdiMetaFile.Adjust( nBrightness, (sal_Int16)nContrast, 0, 0, 0, (double)nGamma / 0x10000, false, true );
if ( eDrawMode == GRAPHICDRAWMODE_GREYS )
aGdiMetaFile.Convert( MTF_CONVERSION_8BIT_GREYS );
else if ( eDrawMode == GRAPHICDRAWMODE_MONO )
diff --git a/include/vcl/bitmap.hxx b/include/vcl/bitmap.hxx
index d555d04e0c1c..4759937e915a 100644
--- a/include/vcl/bitmap.hxx
+++ b/include/vcl/bitmap.hxx
@@ -796,6 +796,9 @@ public:
If sal_True, invert the channel values with the logical 'not' operator
@return sal_True, if the operation was completed successfully.
+
+ @param msoBrightness
+ Use the same formula for brightness as used by MSOffice.
*/
sal_Bool Adjust( short nLuminancePercent = 0,
short nContrastPercent = 0,
@@ -803,7 +806,8 @@ public:
short nChannelGPercent = 0,
short nChannelBPercent = 0,
double fGamma = 1.0,
- sal_Bool bInvert = sal_False );
+ bool bInvert = false,
+ bool msoBrightness = false );
/** Apply specified filter to the bitmap
diff --git a/include/vcl/bitmapex.hxx b/include/vcl/bitmapex.hxx
index 00a3c4e83886..b63c9d5f94d3 100644
--- a/include/vcl/bitmapex.hxx
+++ b/include/vcl/bitmapex.hxx
@@ -344,6 +344,10 @@ public:
If sal_True, invert the channel values with the logical 'not' operator
@return sal_True, if the operation was completed successfully.
+
+ @param msoFormula
+ Use the same formula for brightness as used by MSOffice.
+
*/
sal_Bool Adjust( short nLuminancePercent = 0,
short nContrastPercent = 0,
@@ -351,7 +355,8 @@ public:
short nChannelGPercent = 0,
short nChannelBPercent = 0,
double fGamma = 1.0,
- sal_Bool bInvert = sal_False );
+ bool bInvert = false,
+ bool msoBrightness = false );
/** Apply specified filter to the bitmap
diff --git a/include/vcl/gdimtf.hxx b/include/vcl/gdimtf.hxx
index c790acdd7c43..6865001c2ca7 100644
--- a/include/vcl/gdimtf.hxx
+++ b/include/vcl/gdimtf.hxx
@@ -150,7 +150,7 @@ public:
void Adjust( short nLuminancePercent = 0, short nContrastPercent = 0,
short nChannelRPercent = 0, short nChannelGPercent = 0,
short nChannelBPercent = 0, double fGamma = 1.0,
- sal_Bool bInvert = sal_False
+ bool bInvert = false, bool msoBrightness = false
);
void Convert( MtfConversion eConversion );
diff --git a/vcl/source/gdi/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx
index 5b56ae4d9b7b..354a03b5ece9 100644
--- a/vcl/source/gdi/bitmap3.cxx
+++ b/vcl/source/gdi/bitmap3.cxx
@@ -3271,7 +3271,7 @@ sal_Bool Bitmap::Vectorize( GDIMetaFile& rMtf, sal_uInt8 cReduce, sal_uLong nFla
sal_Bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent,
short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
- double fGamma, sal_Bool bInvert )
+ double fGamma, bool bInvert, bool msoBrightness )
{
sal_Bool bRet = sal_False;
@@ -3303,8 +3303,11 @@ sal_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;
@@ -3318,10 +3321,21 @@ sal_Bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent,
// create mapping table
for( 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 f60c583f1dcd..87564d852be8 100644
--- a/vcl/source/gdi/bitmapex.cxx
+++ b/vcl/source/gdi/bitmapex.cxx
@@ -633,11 +633,11 @@ sal_Bool BitmapEx::Replace( const Color* pSearchColors, const Color* pReplaceCol
sal_Bool BitmapEx::Adjust( short nLuminancePercent, short nContrastPercent,
short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
- double fGamma, sal_Bool bInvert )
+ double fGamma, bool bInvert, bool msoBrightness )
{
return( !!aBitmap ? aBitmap.Adjust( nLuminancePercent, nContrastPercent,
nChannelRPercent, nChannelGPercent, nChannelBPercent,
- fGamma, bInvert ) : sal_False );
+ fGamma, bInvert, msoBrightness ) : false );
}
sal_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 90e691beeed9..17cbb3765bf6 100644
--- a/vcl/source/gdi/gdimtf.cxx
+++ b/vcl/source/gdi/gdimtf.cxx
@@ -2175,7 +2175,7 @@ void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol, const void* pCol
void GDIMetaFile::Adjust( short nLuminancePercent, short nContrastPercent,
short nChannelRPercent, short nChannelGPercent,
- short nChannelBPercent, double fGamma, sal_Bool bInvert )
+ short nChannelBPercent, double fGamma, bool bInvert, bool msoBrightness )
{
// nothing to do? => return quickly
if( nLuminancePercent || nContrastPercent ||
@@ -2196,8 +2196,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;
@@ -2211,10 +2214,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 );