[Libreoffice-commits] core.git: filter/source include/vcl vcl/source

Luboš Luňák l.lunak at collabora.com
Fri Apr 18 11:53:31 PDT 2014


 filter/source/msfilter/msdffimp.cxx |   11 ++++++++---
 include/vcl/bitmap.hxx              |    6 +++++-
 include/vcl/bitmapex.hxx            |    6 +++++-
 include/vcl/gdimtf.hxx              |    2 +-
 vcl/source/gdi/bitmap3.cxx          |   28 +++++++++++++++++++++-------
 vcl/source/gdi/bitmapex.cxx         |    4 ++--
 vcl/source/gdi/gdimtf.cxx           |   25 ++++++++++++++++++-------
 7 files changed, 60 insertions(+), 22 deletions(-)

New commits:
commit 1139d618b8bc6ab823a96184bd0f0257980aad24
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Fri Apr 18 20:46:34 2014 +0200

    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

diff --git a/filter/source/msfilter/msdffimp.cxx b/filter/source/msfilter/msdffimp.cxx
index eb2e91d..30d0ec6 100644
--- a/filter/source/msfilter/msdffimp.cxx
+++ b/filter/source/msfilter/msdffimp.cxx
@@ -3818,7 +3818,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 ) );
@@ -3843,7 +3848,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, 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 )
@@ -3857,7 +3862,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, 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 9485a5a..222cffa 100644
--- a/include/vcl/bitmap.hxx
+++ b/include/vcl/bitmap.hxx
@@ -778,6 +778,9 @@ public:
         @param bInvert
         If true, invert the channel values with the logical 'not' operator
 
+        @param msoBrightness
+        Use the same formula for brightness as used by MSOffice.
+
         @return true, if the operation was completed successfully.
      */
     bool                    Adjust( short nLuminancePercent = 0,
@@ -786,7 +789,8 @@ public:
                                     short nChannelGPercent = 0,
                                     short nChannelBPercent = 0,
                                     double fGamma = 1.0,
-                                    bool bInvert = 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 5fa7c81..5571ee4 100644
--- a/include/vcl/bitmapex.hxx
+++ b/include/vcl/bitmapex.hxx
@@ -348,6 +348,9 @@ public:
         @param bInvert
         If true, invert the channel values with the logical 'not' operator
 
+        @param msoFormula
+        Use the same formula for brightness as used by MSOffice.
+
         @return true, if the operation was completed successfully.
      */
     bool                Adjust( short nLuminancePercent = 0,
@@ -356,7 +359,8 @@ public:
                                 short nChannelGPercent = 0,
                                 short nChannelBPercent = 0,
                                 double fGamma = 1.0,
-                                bool bInvert = 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 0e22e98..4d863aa 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,
-                            bool bInvert = 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 51221ee..5da113f 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 0e41be1..8a5cd09 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 7aee9fa..7107023 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 );


More information about the Libreoffice-commits mailing list