[Libreoffice-commits] core.git: 2 commits - vcl/inc vcl/qa vcl/source

Tomaž Vajngerl (via logerrit) logerrit at kemper.freedesktop.org
Sun Apr 14 12:20:17 UTC 2019


 vcl/inc/bitmap/Octree.hxx     |   60 +++-----------
 vcl/inc/bitmap/impoctree.hxx  |   48 +++++------
 vcl/qa/cppunit/BitmapTest.cxx |   51 +++++++++++
 vcl/source/bitmap/Octree.cxx  |  179 ++++++++++++++++++++++++------------------
 4 files changed, 194 insertions(+), 144 deletions(-)

New commits:
commit eb772683513f4f2b6c8e6404c29b8e477ffc7fad
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Sun Apr 14 16:26:29 2019 +0900
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Sun Apr 14 14:19:34 2019 +0200

    Octree: more clean-up, avoid memset, prefix member vars
    
    Change-Id: I79ec1d0176f523d16c53220de9b0a0d9819729ea
    Reviewed-on: https://gerrit.libreoffice.org/70729
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>

diff --git a/vcl/inc/bitmap/Octree.hxx b/vcl/inc/bitmap/Octree.hxx
index 3e54826a9313..3336c115106f 100644
--- a/vcl/inc/bitmap/Octree.hxx
+++ b/vcl/inc/bitmap/Octree.hxx
@@ -23,9 +23,6 @@
 #include <vcl/salbtype.hxx>
 #include <vcl/dllapi.h>
 
-#define OCTREE_BITS 5
-#define OCTREE_BITS_1 10
-
 struct OctreeNode
 {
     sal_uLong nCount;
@@ -48,51 +45,33 @@ private:
     void CreatePalette(OctreeNode* pNode);
     void GetPalIndex(OctreeNode* pNode);
 
-    SAL_DLLPRIVATE void ImplDeleteOctree(OctreeNode** ppNode);
-    SAL_DLLPRIVATE void ImplAdd(OctreeNode** ppNode);
-    SAL_DLLPRIVATE void ImplReduce();
+    SAL_DLLPRIVATE void deleteOctree(OctreeNode** ppNode);
+    SAL_DLLPRIVATE void add(OctreeNode** ppNode);
+    SAL_DLLPRIVATE void reduce();
 
-    BitmapPalette aPal;
-    sal_uLong nLeafCount;
-    sal_uLong nLevel;
+    BitmapPalette maPalette;
+    sal_uLong mnLeafCount;
+    sal_uLong mnLevel;
     OctreeNode* pTree;
-    OctreeNode* pReduce[OCTREE_BITS + 1];
-    BitmapColor const* pColor;
-    std::unique_ptr<ImpNodeCache> pNodeCache;
-    const BitmapReadAccess* pAcc;
-    sal_uInt16 nPalIndex;
+    std::vector<OctreeNode*> mpReduce;
+    BitmapColor const* mpColor;
+    std::unique_ptr<ImpNodeCache> mpNodeCache;
+    const BitmapReadAccess* mpAccess;
+    sal_uInt16 mnPalIndex;
 
 public:
     Octree(const BitmapReadAccess& rReadAcc, sal_uLong nColors);
     ~Octree();
 
-    inline const BitmapPalette& GetPalette();
-    inline sal_uInt16 GetBestPaletteIndex(const BitmapColor& rColor);
+    const BitmapPalette& GetPalette();
+    sal_uInt16 GetBestPaletteIndex(const BitmapColor& rColor);
 };
 
-inline const BitmapPalette& Octree::GetPalette()
-{
-    aPal.SetEntryCount(static_cast<sal_uInt16>(nLeafCount));
-    nPalIndex = 0;
-    CreatePalette(pTree);
-    return aPal;
-}
-
-inline sal_uInt16 Octree::GetBestPaletteIndex(const BitmapColor& rColor)
-{
-    pColor = &rColor;
-    nPalIndex = 65535;
-    nLevel = 0;
-    GetPalIndex(pTree);
-    return nPalIndex;
-}
-
 class VCL_PLUGIN_PUBLIC InverseColorMap
 {
 private:
-    std::unique_ptr<sal_uInt8[]> pBuffer;
-    std::unique_ptr<sal_uInt8[]> pMap;
-    static constexpr sal_uLong gnBits = 8 - OCTREE_BITS;
+    std::vector<sal_uInt8> mpBuffer;
+    std::vector<sal_uInt8> mpMap;
 
     SAL_DLLPRIVATE void ImplCreateBuffers(const sal_uLong nMax);
 
@@ -100,16 +79,9 @@ public:
     explicit InverseColorMap(const BitmapPalette& rPal);
     ~InverseColorMap();
 
-    inline sal_uInt16 GetBestPaletteIndex(const BitmapColor& rColor);
+    sal_uInt16 GetBestPaletteIndex(const BitmapColor& rColor);
 };
 
-inline sal_uInt16 InverseColorMap::GetBestPaletteIndex(const BitmapColor& rColor)
-{
-    return pMap[((static_cast<sal_uLong>(rColor.GetRed()) >> gnBits) << OCTREE_BITS_1)
-                | ((static_cast<sal_uLong>(rColor.GetGreen()) >> gnBits) << OCTREE_BITS)
-                | (static_cast<sal_uLong>(rColor.GetBlue()) >> gnBits)];
-}
-
 #endif // INCLUDED_VCL_INC_OCTREE_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/bitmap/impoctree.hxx b/vcl/inc/bitmap/impoctree.hxx
index 0ade7b7bcc3b..727551123c5c 100644
--- a/vcl/inc/bitmap/impoctree.hxx
+++ b/vcl/inc/bitmap/impoctree.hxx
@@ -37,9 +37,9 @@ public:
     }
 
     ImpErrorQuad(const BitmapColor& rColor)
-        : nRed(static_cast<long>(rColor.GetRed()) << 5)
-        , nGreen(static_cast<long>(rColor.GetGreen()) << 5)
-        , nBlue(static_cast<long>(rColor.GetBlue()) << 5)
+        : nRed(long(rColor.GetRed()) << 5)
+        , nGreen(long(rColor.GetGreen()) << 5)
+        , nBlue(long(rColor.GetBlue()) << 5)
     {
     }
 
@@ -56,54 +56,52 @@ public:
 
 inline void ImpErrorQuad::operator=(const BitmapColor& rColor)
 {
-    nRed = static_cast<long>(rColor.GetRed()) << 5;
-    nGreen = static_cast<long>(rColor.GetGreen()) << 5;
-    nBlue = static_cast<long>(rColor.GetBlue()) << 5;
+    nRed = long(rColor.GetRed()) << 5;
+    nGreen = long(rColor.GetGreen()) << 5;
+    nBlue = long(rColor.GetBlue()) << 5;
 }
 
 inline ImpErrorQuad& ImpErrorQuad::operator-=(const BitmapColor& rColor)
 {
-    nRed -= (static_cast<long>(rColor.GetRed()) << 5);
-    nGreen -= (static_cast<long>(rColor.GetGreen()) << 5);
-    nBlue -= (static_cast<long>(rColor.GetBlue()) << 5);
+    nRed -= long(rColor.GetRed()) << 5;
+    nGreen -= long(rColor.GetGreen()) << 5;
+    nBlue -= long(rColor.GetBlue()) << 5;
 
     return *this;
 }
 
 inline void ImpErrorQuad::ImplAddColorError1(const ImpErrorQuad& rErrQuad)
 {
-    nRed += (rErrQuad.nRed >> 4);
-    nGreen += (rErrQuad.nGreen >> 4);
-    nBlue += (rErrQuad.nBlue >> 4);
+    nRed += rErrQuad.nRed >> 4;
+    nGreen += rErrQuad.nGreen >> 4;
+    nBlue += rErrQuad.nBlue >> 4;
 }
 
 inline void ImpErrorQuad::ImplAddColorError3(const ImpErrorQuad& rErrQuad)
 {
-    nRed += (rErrQuad.nRed * 3L >> 4);
-    nGreen += (rErrQuad.nGreen * 3L >> 4);
-    nBlue += (rErrQuad.nBlue * 3L >> 4);
+    nRed += rErrQuad.nRed * 3L >> 4;
+    nGreen += rErrQuad.nGreen * 3L >> 4;
+    nBlue += rErrQuad.nBlue * 3L >> 4;
 }
 
 inline void ImpErrorQuad::ImplAddColorError5(const ImpErrorQuad& rErrQuad)
 {
-    nRed += (rErrQuad.nRed * 5L >> 4);
-    nGreen += (rErrQuad.nGreen * 5L >> 4);
-    nBlue += (rErrQuad.nBlue * 5L >> 4);
+    nRed += rErrQuad.nRed * 5L >> 4;
+    nGreen += rErrQuad.nGreen * 5L >> 4;
+    nBlue += rErrQuad.nBlue * 5L >> 4;
 }
 
 inline void ImpErrorQuad::ImplAddColorError7(const ImpErrorQuad& rErrQuad)
 {
-    nRed += (rErrQuad.nRed * 7L >> 4);
-    nGreen += (rErrQuad.nGreen * 7L >> 4);
-    nBlue += (rErrQuad.nBlue * 7L >> 4);
+    nRed += rErrQuad.nRed * 7L >> 4;
+    nGreen += rErrQuad.nGreen * 7L >> 4;
+    nBlue += rErrQuad.nBlue * 7L >> 4;
 }
 
 inline BitmapColor ImpErrorQuad::ImplGetColor()
 {
-    return BitmapColor(
-        static_cast<sal_uInt8>((nRed < 0 ? 0L : nRed > 8160 ? 8160L : nRed) >> 5),
-        static_cast<sal_uInt8>((nGreen < 0 ? 0L : nGreen > 8160 ? 8160L : nGreen) >> 5),
-        static_cast<sal_uInt8>((nBlue < 0 ? 0L : nBlue > 8160 ? 8160L : nBlue) >> 5));
+    return BitmapColor(std::clamp(nRed, 0L, 8160L) >> 5, std::clamp(nGreen, 0L, 8160L) >> 5,
+                       std::clamp(nBlue, 0L, 8160L) >> 5);
 }
 
 class ImpNodeCache
diff --git a/vcl/source/bitmap/Octree.cxx b/vcl/source/bitmap/Octree.cxx
index 6650e52d0692..5f291e6ab8fb 100644
--- a/vcl/source/bitmap/Octree.cxx
+++ b/vcl/source/bitmap/Octree.cxx
@@ -25,7 +25,14 @@
 #include <bitmap/Octree.hxx>
 #include <bitmap/impoctree.hxx>
 
-static const sal_uInt8 pImplMask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
+namespace
+{
+constexpr size_t OCTREE_BITS = 5;
+constexpr size_t OCTREE_BITS_1 = 10;
+
+constexpr sal_uLong gnBits = 8 - OCTREE_BITS;
+
+} // end anonymous namespace
 
 ImpNodeCache::ImpNodeCache(const sal_uLong nInitSize)
     : pActNode(nullptr)
@@ -53,35 +60,35 @@ ImpNodeCache::~ImpNodeCache()
 }
 
 Octree::Octree(const BitmapReadAccess& rReadAcc, sal_uLong nColors)
-    : nLeafCount(0)
-    , nLevel(0)
+    : mnLeafCount(0)
+    , mnLevel(0)
     , pTree(nullptr)
-    , pColor(nullptr)
-    , pAcc(&rReadAcc)
-    , nPalIndex(0)
+    , mpReduce(OCTREE_BITS + 1, nullptr)
+    , mpColor(nullptr)
+    , mpNodeCache(std::make_unique<ImpNodeCache>(nColors))
+    , mpAccess(&rReadAcc)
+    , mnPalIndex(0)
 {
     sal_uLong nMax(nColors);
-    pNodeCache.reset(new ImpNodeCache(nColors));
-    memset(pReduce, 0, (OCTREE_BITS + 1) * sizeof(OctreeNode*));
 
-    if (!!*pAcc)
+    if (!!*mpAccess)
     {
-        const long nWidth = pAcc->Width();
-        const long nHeight = pAcc->Height();
+        const long nWidth = mpAccess->Width();
+        const long nHeight = mpAccess->Height();
 
-        if (pAcc->HasPalette())
+        if (mpAccess->HasPalette())
         {
             for (long nY = 0; nY < nHeight; nY++)
             {
-                Scanline pScanline = pAcc->GetScanline(nY);
+                Scanline pScanline = mpAccess->GetScanline(nY);
                 for (long nX = 0; nX < nWidth; nX++)
                 {
-                    pColor = &pAcc->GetPaletteColor(pAcc->GetIndexFromData(pScanline, nX));
-                    nLevel = 0;
-                    ImplAdd(&pTree);
+                    mpColor = &mpAccess->GetPaletteColor(mpAccess->GetIndexFromData(pScanline, nX));
+                    mnLevel = 0;
+                    add(&pTree);
 
-                    while (nLeafCount > nMax)
-                        ImplReduce();
+                    while (mnLeafCount > nMax)
+                        reduce();
                 }
             }
         }
@@ -89,97 +96,94 @@ Octree::Octree(const BitmapReadAccess& rReadAcc, sal_uLong nColors)
         {
             BitmapColor aColor;
 
-            pColor = &aColor;
+            mpColor = &aColor;
 
             for (long nY = 0; nY < nHeight; nY++)
             {
-                Scanline pScanline = pAcc->GetScanline(nY);
+                Scanline pScanline = mpAccess->GetScanline(nY);
                 for (long nX = 0; nX < nWidth; nX++)
                 {
-                    aColor = pAcc->GetPixelFromData(pScanline, nX);
-                    nLevel = 0;
-                    ImplAdd(&pTree);
+                    aColor = mpAccess->GetPixelFromData(pScanline, nX);
+                    mnLevel = 0;
+                    add(&pTree);
 
-                    while (nLeafCount > nMax)
-                        ImplReduce();
+                    while (mnLeafCount > nMax)
+                        reduce();
                 }
             }
         }
     }
 }
 
-Octree::~Octree()
-{
-    ImplDeleteOctree(&pTree);
-    pNodeCache.reset();
-}
+Octree::~Octree() { deleteOctree(&pTree); }
 
-void Octree::ImplDeleteOctree(OctreeNode** ppNode)
+void Octree::deleteOctree(OctreeNode** ppNode)
 {
     for (OctreeNode* i : (*ppNode)->pChild)
     {
         if (i)
-            ImplDeleteOctree(&i);
+            deleteOctree(&i);
     }
 
-    pNodeCache->ImplReleaseNode(*ppNode);
+    mpNodeCache->ImplReleaseNode(*ppNode);
     *ppNode = nullptr;
 }
 
-void Octree::ImplAdd(OctreeNode** ppNode)
+void Octree::add(OctreeNode** ppNode)
 {
     // possibly generate new nodes
     if (!*ppNode)
     {
-        *ppNode = pNodeCache->ImplGetFreeNode();
-        (*ppNode)->bLeaf = (OCTREE_BITS == nLevel);
+        *ppNode = mpNodeCache->ImplGetFreeNode();
+        (*ppNode)->bLeaf = (OCTREE_BITS == mnLevel);
 
         if ((*ppNode)->bLeaf)
-            nLeafCount++;
+            mnLeafCount++;
         else
         {
-            (*ppNode)->pNext = pReduce[nLevel];
-            pReduce[nLevel] = *ppNode;
+            (*ppNode)->pNext = mpReduce[mnLevel];
+            mpReduce[mnLevel] = *ppNode;
         }
     }
 
     if ((*ppNode)->bLeaf)
     {
         (*ppNode)->nCount++;
-        (*ppNode)->nRed += pColor->GetRed();
-        (*ppNode)->nGreen += pColor->GetGreen();
-        (*ppNode)->nBlue += pColor->GetBlue();
+        (*ppNode)->nRed += mpColor->GetRed();
+        (*ppNode)->nGreen += mpColor->GetGreen();
+        (*ppNode)->nBlue += mpColor->GetBlue();
     }
     else
     {
-        const sal_uLong nShift = 7 - nLevel;
-        const sal_uInt8 cMask = pImplMask[nLevel];
-        const sal_uLong nIndex = (((pColor->GetRed() & cMask) >> nShift) << 2)
-                                 | (((pColor->GetGreen() & cMask) >> nShift) << 1)
-                                 | ((pColor->GetBlue() & cMask) >> nShift);
-
-        nLevel++;
-        ImplAdd(&(*ppNode)->pChild[nIndex]);
+        const sal_uLong nShift = 7 - mnLevel;
+        const sal_uInt8 cMask = 0x80 >> mnLevel;
+        const sal_uLong nIndex = (((mpColor->GetRed() & cMask) >> nShift) << 2)
+                                 | (((mpColor->GetGreen() & cMask) >> nShift) << 1)
+                                 | ((mpColor->GetBlue() & cMask) >> nShift);
+
+        mnLevel++;
+        add(&(*ppNode)->pChild[nIndex]);
     }
 }
 
-void Octree::ImplReduce()
+void Octree::reduce()
 {
-    sal_uLong i;
     OctreeNode* pNode;
     sal_uLong nRedSum = 0;
     sal_uLong nGreenSum = 0;
     sal_uLong nBlueSum = 0;
     sal_uLong nChildren = 0;
 
-    for (i = OCTREE_BITS - 1; i && !pReduce[i]; i--)
+    sal_uLong nIndex = OCTREE_BITS - 1;
+    while (nIndex > 0 && !mpReduce[nIndex])
     {
+        nIndex--;
     }
 
-    pNode = pReduce[i];
-    pReduce[i] = pNode->pNext;
+    pNode = mpReduce[nIndex];
+    mpReduce[nIndex] = pNode->pNext;
 
-    for (i = 0; i < 8; i++)
+    for (sal_uLong i = 0; i < 8; i++)
     {
         if (pNode->pChild[i])
         {
@@ -190,7 +194,7 @@ void Octree::ImplReduce()
             nBlueSum += pChild->nBlue;
             pNode->nCount += pChild->nCount;
 
-            pNodeCache->ImplReleaseNode(pNode->pChild[i]);
+            mpNodeCache->ImplReleaseNode(pNode->pChild[i]);
             pNode->pChild[i] = nullptr;
             nChildren++;
         }
@@ -200,43 +204,64 @@ void Octree::ImplReduce()
     pNode->nRed = nRedSum;
     pNode->nGreen = nGreenSum;
     pNode->nBlue = nBlueSum;
-    nLeafCount -= --nChildren;
+    mnLeafCount -= --nChildren;
 }
 
 void Octree::CreatePalette(OctreeNode* pNode)
 {
     if (pNode->bLeaf)
     {
-        pNode->nPalIndex = nPalIndex;
-        aPal[nPalIndex++] = BitmapColor(
-            static_cast<sal_uInt8>(static_cast<double>(pNode->nRed) / pNode->nCount),
-            static_cast<sal_uInt8>(static_cast<double>(pNode->nGreen) / pNode->nCount),
-            static_cast<sal_uInt8>(static_cast<double>(pNode->nBlue) / pNode->nCount));
+        pNode->nPalIndex = mnPalIndex;
+        maPalette[mnPalIndex++] = BitmapColor(sal_uInt8(double(pNode->nRed) / pNode->nCount),
+                                              sal_uInt8(double(pNode->nGreen) / pNode->nCount),
+                                              sal_uInt8(double(pNode->nBlue) / pNode->nCount));
     }
     else
+    {
         for (OctreeNode* i : pNode->pChild)
         {
             if (i)
+            {
                 CreatePalette(i);
+            }
         }
+    }
 }
 
 void Octree::GetPalIndex(OctreeNode* pNode)
 {
     if (pNode->bLeaf)
-        nPalIndex = pNode->nPalIndex;
+        mnPalIndex = pNode->nPalIndex;
     else
     {
-        const sal_uLong nShift = 7 - nLevel;
-        const sal_uInt8 cMask = pImplMask[nLevel++];
-        const sal_uLong nIndex = (((pColor->GetRed() & cMask) >> nShift) << 2)
-                                 | (((pColor->GetGreen() & cMask) >> nShift) << 1)
-                                 | ((pColor->GetBlue() & cMask) >> nShift);
+        const sal_uLong nShift = 7 - mnLevel;
+        const sal_uInt8 cMask = 0x80 >> mnLevel;
+        mnLevel++;
+        const sal_uLong nIndex = (((mpColor->GetRed() & cMask) >> nShift) << 2)
+                                 | (((mpColor->GetGreen() & cMask) >> nShift) << 1)
+                                 | ((mpColor->GetBlue() & cMask) >> nShift);
 
         GetPalIndex(pNode->pChild[nIndex]);
     }
 }
 
+const BitmapPalette& Octree::GetPalette()
+{
+    maPalette.SetEntryCount(sal_uInt16(mnLeafCount));
+    mnPalIndex = 0;
+    CreatePalette(pTree);
+    return maPalette;
+}
+
+sal_uInt16 Octree::GetBestPaletteIndex(const BitmapColor& rColor)
+{
+    mpColor = &rColor;
+    mnPalIndex = 65535;
+    mnLevel = 0;
+    GetPalIndex(pTree);
+    return mnPalIndex;
+}
+
 InverseColorMap::InverseColorMap(const BitmapPalette& rPal)
 {
     const int nColorMax = 1 << OCTREE_BITS;
@@ -266,8 +291,8 @@ InverseColorMap::InverseColorMap(const BitmapPalette& rPal)
         const long cginc = (xsqr - (cGreen << gnBits)) << 1;
         const long cbinc = (xsqr - (cBlue << gnBits)) << 1;
 
-        sal_uLong* cdp = reinterpret_cast<sal_uLong*>(pBuffer.get());
-        sal_uInt8* crgbp = pMap.get();
+        sal_uLong* cdp = reinterpret_cast<sal_uLong*>(mpBuffer.data());
+        sal_uInt8* crgbp = mpMap.data();
 
         for (r = 0, rxx = crinc; r < nColorMax; rdist += rxx, r++, rxx += xsqr2)
         {
@@ -292,11 +317,15 @@ void InverseColorMap::ImplCreateBuffers(const sal_uLong nMax)
     const sal_uLong nCount = nMax * nMax * nMax;
     const sal_uLong nSize = nCount * sizeof(sal_uLong);
 
-    pMap.reset(new sal_uInt8[nCount]);
-    memset(pMap.get(), 0x00, nCount);
+    mpMap.resize(nCount, 0x00);
+    mpBuffer.resize(nSize, 0xff);
+}
 
-    pBuffer.reset(new sal_uInt8[nSize]);
-    memset(pBuffer.get(), 0xff, nSize);
+sal_uInt16 InverseColorMap::GetBestPaletteIndex(const BitmapColor& rColor)
+{
+    return mpMap[((static_cast<sal_uLong>(rColor.GetRed()) >> gnBits) << OCTREE_BITS_1)
+                 | ((static_cast<sal_uLong>(rColor.GetGreen()) >> gnBits) << OCTREE_BITS)
+                 | (static_cast<sal_uLong>(rColor.GetBlue()) >> gnBits)];
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 58187ebf61ddba6574f59bc396c327f76fb48967
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Sun Apr 14 15:37:05 2019 +0900
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Sun Apr 14 14:19:18 2019 +0200

    vcl: add a basic Octree test
    
    Change-Id: I4f142586ceedb8f51610139db914845892f65d2c
    Reviewed-on: https://gerrit.libreoffice.org/70728
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>

diff --git a/vcl/qa/cppunit/BitmapTest.cxx b/vcl/qa/cppunit/BitmapTest.cxx
index 52abfb6c10e5..6dd6053bed18 100644
--- a/vcl/qa/cppunit/BitmapTest.cxx
+++ b/vcl/qa/cppunit/BitmapTest.cxx
@@ -32,6 +32,7 @@
 
 #include <svdata.hxx>
 #include <salinst.hxx>
+#include <bitmap/Octree.hxx>
 
 namespace
 {
@@ -50,6 +51,7 @@ class BitmapTest : public CppUnit::TestFixture
     void testCustom8BitPalette();
     void testErase();
     void testBitmap32();
+    void testOctree();
 
     CPPUNIT_TEST_SUITE(BitmapTest);
     CPPUNIT_TEST(testCreation);
@@ -65,6 +67,7 @@ class BitmapTest : public CppUnit::TestFixture
     CPPUNIT_TEST(testCustom8BitPalette);
     CPPUNIT_TEST(testErase);
     CPPUNIT_TEST(testBitmap32);
+    CPPUNIT_TEST(testOctree);
     CPPUNIT_TEST_SUITE_END();
 };
 
@@ -741,6 +744,54 @@ void BitmapTest::testBitmap32()
     }
 }
 
+void BitmapTest::testOctree()
+{
+    Size aSize(1000, 100);
+    Bitmap aBitmap(aSize, 24);
+    {
+        BitmapScopedWriteAccess pWriteAccess(aBitmap);
+        for (long y = 0; y < aSize.Height(); ++y)
+        {
+            for (long x = 0; x < aSize.Width(); ++x)
+            {
+                double fPercent = double(x) / double(aSize.Width());
+                pWriteAccess->SetPixel(y, x,
+                                       BitmapColor(255.0 * fPercent, 64.0 + (128.0 * fPercent),
+                                                   255.0 - 255.0 * fPercent));
+            }
+        }
+    }
+
+    {
+        // Reduce to 1 color
+        Bitmap::ScopedReadAccess pAccess(aBitmap);
+        Octree aOctree(*pAccess.get(), 1);
+        auto aBitmapPalette = aOctree.GetPalette();
+        CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), aBitmapPalette.GetEntryCount());
+        CPPUNIT_ASSERT_EQUAL(BitmapColor(0x7e, 0x7f, 0x7f), aBitmapPalette[0]);
+    }
+
+    {
+        // Reduce to 4 color
+        Bitmap::ScopedReadAccess pAccess(aBitmap);
+        Octree aOctree(*pAccess.get(), 4);
+        auto aBitmapPalette = aOctree.GetPalette();
+        CPPUNIT_ASSERT_EQUAL(sal_uInt16(4), aBitmapPalette.GetEntryCount());
+        CPPUNIT_ASSERT_EQUAL(BitmapColor(0x7f, 0x7f, 0x7f), aBitmapPalette[0]);
+        CPPUNIT_ASSERT_EQUAL(BitmapColor(0x3e, 0x5f, 0xbf), aBitmapPalette[1]);
+        CPPUNIT_ASSERT_EQUAL(BitmapColor(0x7f, 0x80, 0x7f), aBitmapPalette[2]);
+        CPPUNIT_ASSERT_EQUAL(BitmapColor(0xbe, 0x9f, 0x3f), aBitmapPalette[3]);
+    }
+
+    {
+        // Reduce to 256 color
+        Bitmap::ScopedReadAccess pAccess(aBitmap);
+        Octree aOctree(*pAccess.get(), 256);
+        auto aBitmapPalette = aOctree.GetPalette();
+        CPPUNIT_ASSERT_EQUAL(sal_uInt16(74), aBitmapPalette.GetEntryCount());
+    }
+}
+
 } // namespace
 
 CPPUNIT_TEST_SUITE_REGISTRATION(BitmapTest);


More information about the Libreoffice-commits mailing list