office-gobmx/vcl/source/bitmap/Octree.cxx
Stephan Bergmann 5db574727f Avoid -Werror=dangling-pointer=
> vcl/source/bitmap/Octree.cxx: In constructor ‘Octree::Octree(const BitmapReadAccess&, sal_uLong)’:
> vcl/source/bitmap/Octree.cxx:69:17: error: storing the address of local variable ‘aColor’ in ‘*this.Octree::mpColor’ [-Werror=dangling-pointer=]
>    69 |         mpColor = &aColor;
>       |         ~~~~~~~~^~~~~~~~~
> vcl/source/bitmap/Octree.cxx:67:21: note: ‘aColor’ declared here
>    67 |         BitmapColor aColor;
>       |                     ^~~~~~
> vcl/source/bitmap/Octree.cxx:67:21: note: ‘<unknown>’ declared here

(new with GCC 12)

Change-Id: I5b1ffa15b92f2c41dbe51dfa843eb6bab3a4b449
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128517
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2022-01-17 22:38:13 +01:00

280 lines
8.1 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <vcl/BitmapReadAccess.hxx>
#include <bitmap/Octree.hxx>
namespace
{
constexpr size_t OCTREE_BITS = 5;
constexpr size_t OCTREE_BITS_1 = 10;
constexpr sal_uLong gnBits = 8 - OCTREE_BITS;
} // end anonymous namespace
Octree::Octree(const BitmapReadAccess& rReadAcc, sal_uLong nColors)
: mnLeafCount(0)
, mnLevel(0)
, mpReduce(OCTREE_BITS + 1, nullptr)
, mnPalIndex(0)
{
const BitmapReadAccess* pAccess = &rReadAcc;
sal_uLong nMax(nColors);
if (!*pAccess)
return;
const tools::Long nWidth = pAccess->Width();
const tools::Long nHeight = pAccess->Height();
if (pAccess->HasPalette())
{
for (tools::Long nY = 0; nY < nHeight; nY++)
{
Scanline pScanline = pAccess->GetScanline(nY);
for (tools::Long nX = 0; nX < nWidth; nX++)
{
mnLevel = 0;
add(pTree, pAccess->GetPaletteColor(pAccess->GetIndexFromData(pScanline, nX)));
while (mnLeafCount > nMax)
reduce();
}
}
}
else
{
for (tools::Long nY = 0; nY < nHeight; nY++)
{
Scanline pScanline = pAccess->GetScanline(nY);
for (tools::Long nX = 0; nX < nWidth; nX++)
{
mnLevel = 0;
add(pTree, pAccess->GetPixelFromData(pScanline, nX));
while (mnLeafCount > nMax)
reduce();
}
}
}
}
Octree::~Octree() {}
void Octree::add(std::unique_ptr<OctreeNode>& rpNode, BitmapColor const& color)
{
// possibly generate new nodes
if (!rpNode)
{
rpNode.reset(new OctreeNode);
rpNode->bLeaf = (OCTREE_BITS == mnLevel);
if (rpNode->bLeaf)
mnLeafCount++;
else
{
rpNode->pNext = mpReduce[mnLevel];
mpReduce[mnLevel] = rpNode.get();
}
}
if (rpNode->bLeaf)
{
rpNode->nCount++;
rpNode->nRed += color.GetRed();
rpNode->nGreen += color.GetGreen();
rpNode->nBlue += color.GetBlue();
}
else
{
const sal_uLong nShift = 7 - mnLevel;
const sal_uInt8 cMask = 0x80 >> mnLevel;
const sal_uLong nIndex = (((color.GetRed() & cMask) >> nShift) << 2)
| (((color.GetGreen() & cMask) >> nShift) << 1)
| ((color.GetBlue() & cMask) >> nShift);
mnLevel++;
add(rpNode->pChild[nIndex], color);
}
}
void Octree::reduce()
{
OctreeNode* pNode;
sal_uLong nRedSum = 0;
sal_uLong nGreenSum = 0;
sal_uLong nBlueSum = 0;
sal_uLong nChildren = 0;
sal_uLong nIndex = OCTREE_BITS - 1;
while (nIndex > 0 && !mpReduce[nIndex])
{
nIndex--;
}
pNode = mpReduce[nIndex];
mpReduce[nIndex] = pNode->pNext;
for (unsigned int i = 0; i < 8; i++)
{
if (pNode->pChild[i])
{
OctreeNode* pChild = pNode->pChild[i].get();
nRedSum += pChild->nRed;
nGreenSum += pChild->nGreen;
nBlueSum += pChild->nBlue;
pNode->nCount += pChild->nCount;
pNode->pChild[i].reset();
nChildren++;
}
}
pNode->bLeaf = true;
pNode->nRed = nRedSum;
pNode->nGreen = nGreenSum;
pNode->nBlue = nBlueSum;
mnLeafCount -= --nChildren;
}
void Octree::CreatePalette(OctreeNode* pNode)
{
if (pNode->bLeaf)
{
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 (auto const& i : pNode->pChild)
{
if (i)
{
CreatePalette(i.get());
}
}
}
}
void Octree::GetPalIndex(const OctreeNode* pNode, BitmapColor const& color)
{
if (pNode->bLeaf)
mnPalIndex = pNode->nPalIndex;
else
{
const sal_uLong nShift = 7 - mnLevel;
const sal_uInt8 cMask = 0x80 >> mnLevel;
mnLevel++;
const sal_uLong nIndex = (((color.GetRed() & cMask) >> nShift) << 2)
| (((color.GetGreen() & cMask) >> nShift) << 1)
| ((color.GetBlue() & cMask) >> nShift);
GetPalIndex(pNode->pChild[nIndex].get(), color);
}
}
const BitmapPalette& Octree::GetPalette()
{
maPalette.SetEntryCount(sal_uInt16(mnLeafCount));
mnPalIndex = 0;
CreatePalette(pTree.get());
return maPalette;
}
sal_uInt16 Octree::GetBestPaletteIndex(const BitmapColor& rColor)
{
mnPalIndex = 65535;
mnLevel = 0;
GetPalIndex(pTree.get(), rColor);
return mnPalIndex;
}
constexpr int nColorMax = 1 << OCTREE_BITS;
InverseColorMap::InverseColorMap(const BitmapPalette& rPal)
{
const unsigned long xsqr = 1 << (gnBits << 1);
const unsigned long xsqr2 = xsqr << 1;
const int nColors = rPal.GetEntryCount();
const tools::Long x = 1 << gnBits;
const tools::Long x2 = x >> 1;
sal_uLong r, g, b;
tools::Long rxx, gxx, bxx;
ImplCreateBuffers();
for (int nIndex = 0; nIndex < nColors; nIndex++)
{
const BitmapColor& rColor = rPal[static_cast<sal_uInt16>(nIndex)];
const tools::Long cRed = rColor.GetRed();
const tools::Long cGreen = rColor.GetGreen();
const tools::Long cBlue = rColor.GetBlue();
tools::Long rdist = cRed - x2;
tools::Long gdist = cGreen - x2;
tools::Long bdist = cBlue - x2;
rdist = rdist * rdist + gdist * gdist + bdist * bdist;
const tools::Long crinc = (xsqr - (cRed << gnBits)) << 1;
const tools::Long cginc = (xsqr - (cGreen << gnBits)) << 1;
const tools::Long cbinc = (xsqr - (cBlue << gnBits)) << 1;
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)
{
for (g = 0, gdist = rdist, gxx = cginc; g < nColorMax; gdist += gxx, g++, gxx += xsqr2)
{
for (b = 0, bdist = gdist, bxx = cbinc; b < nColorMax;
bdist += bxx, b++, cdp++, crgbp++, bxx += xsqr2)
if (!nIndex || static_cast<tools::Long>(*cdp) > bdist)
{
*cdp = bdist;
*crgbp = static_cast<sal_uInt8>(nIndex);
}
}
}
}
}
InverseColorMap::~InverseColorMap() {}
void InverseColorMap::ImplCreateBuffers()
{
const sal_uLong nCount = nColorMax * nColorMax * nColorMax;
const sal_uLong nSize = nCount * sizeof(sal_uLong);
mpMap.resize(nCount, 0x00);
mpBuffer.resize(nSize, 0xff);
}
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: */