flatten some code in vcl

Change-Id: I29638408d60bfa02609ed58839829ed51d319e98
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145045
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
This commit is contained in:
Noel Grandin
2023-01-05 17:00:54 +00:00
committed by Noel Grandin
parent a8d3b8985a
commit 0461eb7564
4 changed files with 474 additions and 533 deletions
@@ -23,202 +23,179 @@ BitmapEx BitmapColorQuantizationFilter::execute(BitmapEx const& aBitmapEx) const
{
Bitmap aBitmap = aBitmapEx.GetBitmap();
bool bRet = false;
if (vcl::numberOfColors(aBitmap.getPixelFormat()) <= sal_Int64(mnNewColorCount))
{
bRet = true;
}
else
{
Bitmap::ScopedReadAccess pRAcc(aBitmap);
return BitmapEx(aBitmap);
auto const cappedNewColorCount = std::min(mnNewColorCount, sal_uInt16(256));
Bitmap::ScopedReadAccess pRAcc(aBitmap);
if (!pRAcc)
return BitmapEx();
if (pRAcc)
auto const cappedNewColorCount = std::min(mnNewColorCount, sal_uInt16(256));
const sal_uInt32 nValidBits = 4;
const sal_uInt32 nRightShiftBits = 8 - nValidBits;
const sal_uInt32 nLeftShiftBits1 = nValidBits;
const sal_uInt32 nLeftShiftBits2 = nValidBits << 1;
const sal_uInt32 nColorsPerComponent = 1 << nValidBits;
const sal_uInt32 nColorOffset = 256 / nColorsPerComponent;
const sal_uInt32 nTotalColors = nColorsPerComponent * nColorsPerComponent * nColorsPerComponent;
const sal_Int32 nWidth = pRAcc->Width();
const sal_Int32 nHeight = pRAcc->Height();
std::unique_ptr<PopularColorCount[]> pCountTable(new PopularColorCount[nTotalColors]);
memset(pCountTable.get(), 0, nTotalColors * sizeof(PopularColorCount));
for (sal_Int32 nR = 0, nIndex = 0; nR < 256; nR += nColorOffset)
{
for (sal_Int32 nG = 0; nG < 256; nG += nColorOffset)
{
const sal_uInt32 nValidBits = 4;
const sal_uInt32 nRightShiftBits = 8 - nValidBits;
const sal_uInt32 nLeftShiftBits1 = nValidBits;
const sal_uInt32 nLeftShiftBits2 = nValidBits << 1;
const sal_uInt32 nColorsPerComponent = 1 << nValidBits;
const sal_uInt32 nColorOffset = 256 / nColorsPerComponent;
const sal_uInt32 nTotalColors
= nColorsPerComponent * nColorsPerComponent * nColorsPerComponent;
const sal_Int32 nWidth = pRAcc->Width();
const sal_Int32 nHeight = pRAcc->Height();
std::unique_ptr<PopularColorCount[]> pCountTable(new PopularColorCount[nTotalColors]);
memset(pCountTable.get(), 0, nTotalColors * sizeof(PopularColorCount));
for (sal_Int32 nR = 0, nIndex = 0; nR < 256; nR += nColorOffset)
for (sal_Int32 nB = 0; nB < 256; nB += nColorOffset)
{
for (sal_Int32 nG = 0; nG < 256; nG += nColorOffset)
{
for (sal_Int32 nB = 0; nB < 256; nB += nColorOffset)
{
pCountTable[nIndex].mnIndex = nIndex;
nIndex++;
}
}
}
if (pRAcc->HasPalette())
{
for (sal_Int32 nY = 0; nY < nHeight; nY++)
{
Scanline pScanlineRead = pRAcc->GetScanline(nY);
for (sal_Int32 nX = 0; nX < nWidth; nX++)
{
const BitmapColor& rCol
= pRAcc->GetPaletteColor(pRAcc->GetIndexFromData(pScanlineRead, nX));
pCountTable[((static_cast<sal_uInt32>(rCol.GetRed()) >> nRightShiftBits)
<< nLeftShiftBits2)
| ((static_cast<sal_uInt32>(rCol.GetGreen()) >> nRightShiftBits)
<< nLeftShiftBits1)
| (static_cast<sal_uInt32>(rCol.GetBlue()) >> nRightShiftBits)]
.mnCount++;
}
}
}
else
{
for (sal_Int32 nY = 0; nY < nHeight; nY++)
{
Scanline pScanlineRead = pRAcc->GetScanline(nY);
for (sal_Int32 nX = 0; nX < nWidth; nX++)
{
const BitmapColor aCol(pRAcc->GetPixelFromData(pScanlineRead, nX));
pCountTable[((static_cast<sal_uInt32>(aCol.GetRed()) >> nRightShiftBits)
<< nLeftShiftBits2)
| ((static_cast<sal_uInt32>(aCol.GetGreen()) >> nRightShiftBits)
<< nLeftShiftBits1)
| (static_cast<sal_uInt32>(aCol.GetBlue()) >> nRightShiftBits)]
.mnCount++;
}
}
}
BitmapPalette aNewPal(cappedNewColorCount);
std::qsort(pCountTable.get(), nTotalColors, sizeof(PopularColorCount),
[](const void* p1, const void* p2) {
int nRet;
if (static_cast<PopularColorCount const*>(p1)->mnCount
< static_cast<PopularColorCount const*>(p2)->mnCount)
nRet = 1;
else if (static_cast<PopularColorCount const*>(p1)->mnCount
== static_cast<PopularColorCount const*>(p2)->mnCount)
nRet = 0;
else
nRet = -1;
return nRet;
});
for (sal_uInt16 n = 0; n < cappedNewColorCount; n++)
{
const PopularColorCount& rPop = pCountTable[n];
aNewPal[n] = BitmapColor(
static_cast<sal_uInt8>((rPop.mnIndex >> nLeftShiftBits2) << nRightShiftBits),
static_cast<sal_uInt8>(
((rPop.mnIndex >> nLeftShiftBits1) & (nColorsPerComponent - 1))
<< nRightShiftBits),
static_cast<sal_uInt8>((rPop.mnIndex & (nColorsPerComponent - 1))
<< nRightShiftBits));
}
Bitmap aNewBmp(aBitmap.GetSizePixel(), vcl::PixelFormat::N8_BPP, &aNewPal);
BitmapScopedWriteAccess pWAcc(aNewBmp);
if (pWAcc)
{
BitmapColor aDstCol(sal_uInt8(0));
std::unique_ptr<sal_uInt8[]> pIndexMap(new sal_uInt8[nTotalColors]);
for (sal_Int32 nR = 0, nIndex = 0; nR < 256; nR += nColorOffset)
{
for (sal_Int32 nG = 0; nG < 256; nG += nColorOffset)
{
for (sal_Int32 nB = 0; nB < 256; nB += nColorOffset)
{
pIndexMap[nIndex++] = static_cast<sal_uInt8>(aNewPal.GetBestIndex(
BitmapColor(static_cast<sal_uInt8>(nR), static_cast<sal_uInt8>(nG),
static_cast<sal_uInt8>(nB))));
}
}
}
if (pRAcc->HasPalette())
{
for (sal_Int32 nY = 0; nY < nHeight; nY++)
{
Scanline pScanline = pWAcc->GetScanline(nY);
Scanline pScanlineRead = pRAcc->GetScanline(nY);
for (sal_Int32 nX = 0; nX < nWidth; nX++)
{
const BitmapColor& rCol = pRAcc->GetPaletteColor(
pRAcc->GetIndexFromData(pScanlineRead, nX));
aDstCol.SetIndex(pIndexMap[((static_cast<sal_uInt32>(rCol.GetRed())
>> nRightShiftBits)
<< nLeftShiftBits2)
| ((static_cast<sal_uInt32>(rCol.GetGreen())
>> nRightShiftBits)
<< nLeftShiftBits1)
| (static_cast<sal_uInt32>(rCol.GetBlue())
>> nRightShiftBits)]);
pWAcc->SetPixelOnData(pScanline, nX, aDstCol);
}
}
}
else
{
for (sal_Int32 nY = 0; nY < nHeight; nY++)
{
Scanline pScanline = pWAcc->GetScanline(nY);
Scanline pScanlineRead = pRAcc->GetScanline(nY);
for (sal_Int32 nX = 0; nX < nWidth; nX++)
{
const BitmapColor aCol(pRAcc->GetPixelFromData(pScanlineRead, nX));
aDstCol.SetIndex(pIndexMap[((static_cast<sal_uInt32>(aCol.GetRed())
>> nRightShiftBits)
<< nLeftShiftBits2)
| ((static_cast<sal_uInt32>(aCol.GetGreen())
>> nRightShiftBits)
<< nLeftShiftBits1)
| (static_cast<sal_uInt32>(aCol.GetBlue())
>> nRightShiftBits)]);
pWAcc->SetPixelOnData(pScanline, nX, aDstCol);
}
}
}
pWAcc.reset();
bRet = true;
}
pCountTable.reset();
pRAcc.reset();
if (bRet)
{
const MapMode aMap(aBitmap.GetPrefMapMode());
const Size aSize(aBitmap.GetPrefSize());
aBitmap = aNewBmp;
aBitmap.SetPrefMapMode(aMap);
aBitmap.SetPrefSize(aSize);
pCountTable[nIndex].mnIndex = nIndex;
nIndex++;
}
}
}
if (bRet)
return BitmapEx(aBitmap);
if (pRAcc->HasPalette())
{
for (sal_Int32 nY = 0; nY < nHeight; nY++)
{
Scanline pScanlineRead = pRAcc->GetScanline(nY);
for (sal_Int32 nX = 0; nX < nWidth; nX++)
{
const BitmapColor& rCol
= pRAcc->GetPaletteColor(pRAcc->GetIndexFromData(pScanlineRead, nX));
pCountTable[((static_cast<sal_uInt32>(rCol.GetRed()) >> nRightShiftBits)
<< nLeftShiftBits2)
| ((static_cast<sal_uInt32>(rCol.GetGreen()) >> nRightShiftBits)
<< nLeftShiftBits1)
| (static_cast<sal_uInt32>(rCol.GetBlue()) >> nRightShiftBits)]
.mnCount++;
}
}
}
else
{
for (sal_Int32 nY = 0; nY < nHeight; nY++)
{
Scanline pScanlineRead = pRAcc->GetScanline(nY);
for (sal_Int32 nX = 0; nX < nWidth; nX++)
{
const BitmapColor aCol(pRAcc->GetPixelFromData(pScanlineRead, nX));
pCountTable[((static_cast<sal_uInt32>(aCol.GetRed()) >> nRightShiftBits)
<< nLeftShiftBits2)
| ((static_cast<sal_uInt32>(aCol.GetGreen()) >> nRightShiftBits)
<< nLeftShiftBits1)
| (static_cast<sal_uInt32>(aCol.GetBlue()) >> nRightShiftBits)]
.mnCount++;
}
}
}
return BitmapEx();
BitmapPalette aNewPal(cappedNewColorCount);
std::qsort(pCountTable.get(), nTotalColors, sizeof(PopularColorCount),
[](const void* p1, const void* p2) {
int nRet;
if (static_cast<PopularColorCount const*>(p1)->mnCount
< static_cast<PopularColorCount const*>(p2)->mnCount)
nRet = 1;
else if (static_cast<PopularColorCount const*>(p1)->mnCount
== static_cast<PopularColorCount const*>(p2)->mnCount)
nRet = 0;
else
nRet = -1;
return nRet;
});
for (sal_uInt16 n = 0; n < cappedNewColorCount; n++)
{
const PopularColorCount& rPop = pCountTable[n];
aNewPal[n] = BitmapColor(
static_cast<sal_uInt8>((rPop.mnIndex >> nLeftShiftBits2) << nRightShiftBits),
static_cast<sal_uInt8>(((rPop.mnIndex >> nLeftShiftBits1) & (nColorsPerComponent - 1))
<< nRightShiftBits),
static_cast<sal_uInt8>((rPop.mnIndex & (nColorsPerComponent - 1)) << nRightShiftBits));
}
Bitmap aNewBmp(aBitmap.GetSizePixel(), vcl::PixelFormat::N8_BPP, &aNewPal);
BitmapScopedWriteAccess pWAcc(aNewBmp);
if (!pWAcc)
return BitmapEx();
BitmapColor aDstCol(sal_uInt8(0));
std::unique_ptr<sal_uInt8[]> pIndexMap(new sal_uInt8[nTotalColors]);
for (sal_Int32 nR = 0, nIndex = 0; nR < 256; nR += nColorOffset)
{
for (sal_Int32 nG = 0; nG < 256; nG += nColorOffset)
{
for (sal_Int32 nB = 0; nB < 256; nB += nColorOffset)
{
pIndexMap[nIndex++] = static_cast<sal_uInt8>(aNewPal.GetBestIndex(
BitmapColor(static_cast<sal_uInt8>(nR), static_cast<sal_uInt8>(nG),
static_cast<sal_uInt8>(nB))));
}
}
}
if (pRAcc->HasPalette())
{
for (sal_Int32 nY = 0; nY < nHeight; nY++)
{
Scanline pScanline = pWAcc->GetScanline(nY);
Scanline pScanlineRead = pRAcc->GetScanline(nY);
for (sal_Int32 nX = 0; nX < nWidth; nX++)
{
const BitmapColor& rCol
= pRAcc->GetPaletteColor(pRAcc->GetIndexFromData(pScanlineRead, nX));
aDstCol.SetIndex(
pIndexMap[((static_cast<sal_uInt32>(rCol.GetRed()) >> nRightShiftBits)
<< nLeftShiftBits2)
| ((static_cast<sal_uInt32>(rCol.GetGreen()) >> nRightShiftBits)
<< nLeftShiftBits1)
| (static_cast<sal_uInt32>(rCol.GetBlue()) >> nRightShiftBits)]);
pWAcc->SetPixelOnData(pScanline, nX, aDstCol);
}
}
}
else
{
for (sal_Int32 nY = 0; nY < nHeight; nY++)
{
Scanline pScanline = pWAcc->GetScanline(nY);
Scanline pScanlineRead = pRAcc->GetScanline(nY);
for (sal_Int32 nX = 0; nX < nWidth; nX++)
{
const BitmapColor aCol(pRAcc->GetPixelFromData(pScanlineRead, nX));
aDstCol.SetIndex(
pIndexMap[((static_cast<sal_uInt32>(aCol.GetRed()) >> nRightShiftBits)
<< nLeftShiftBits2)
| ((static_cast<sal_uInt32>(aCol.GetGreen()) >> nRightShiftBits)
<< nLeftShiftBits1)
| (static_cast<sal_uInt32>(aCol.GetBlue()) >> nRightShiftBits)]);
pWAcc->SetPixelOnData(pScanline, nX, aDstCol);
}
}
}
pWAcc.reset();
pCountTable.reset();
pRAcc.reset();
const MapMode aMap(aBitmap.GetPrefMapMode());
const Size aSize(aBitmap.GetPrefSize());
aBitmap = aNewBmp;
aBitmap.SetPrefMapMode(aMap);
aBitmap.SetPrefSize(aSize);
return BitmapEx(aBitmap);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@@ -25,179 +25,167 @@ BitmapEx BitmapConvolutionMatrixFilter::execute(BitmapEx const& rBitmapEx) const
const sal_Int32 nDivisor = 8;
Bitmap::ScopedReadAccess pReadAcc(aBitmap);
bool bRet = false;
if (!pReadAcc)
return BitmapEx();
if (pReadAcc)
Bitmap aNewBmp(aBitmap.GetSizePixel(), vcl::PixelFormat::N24_BPP);
BitmapScopedWriteAccess pWriteAcc(aNewBmp);
if (!pWriteAcc)
return BitmapEx();
const sal_Int32 nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
const sal_Int32 nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
std::unique_ptr<sal_Int32[]> pColm(new sal_Int32[nWidth2]);
std::unique_ptr<sal_Int32[]> pRows(new sal_Int32[nHeight2]);
std::unique_ptr<BitmapColor[]> pColRow1(new BitmapColor[nWidth2]);
std::unique_ptr<BitmapColor[]> pColRow2(new BitmapColor[nWidth2]);
std::unique_ptr<BitmapColor[]> pColRow3(new BitmapColor[nWidth2]);
BitmapColor* pRowTmp1 = pColRow1.get();
BitmapColor* pRowTmp2 = pColRow2.get();
BitmapColor* pRowTmp3 = pColRow3.get();
BitmapColor* pColor;
sal_Int32 nY, nX, i, nSumR, nSumG, nSumB, nMatrixVal, nTmp;
std::array<std::array<sal_Int32, 256>, 9> aKoeff;
sal_Int32* pTmp;
// create LUT of products of matrix value and possible color component values
for (nY = 0; nY < 9; nY++)
{
Bitmap aNewBmp(aBitmap.GetSizePixel(), vcl::PixelFormat::N24_BPP);
BitmapScopedWriteAccess pWriteAcc(aNewBmp);
if (pWriteAcc)
for (nX = nTmp = 0, nMatrixVal = mrMatrix[nY]; nX < 256; nX++, nTmp += nMatrixVal)
{
const sal_Int32 nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
const sal_Int32 nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
std::unique_ptr<sal_Int32[]> pColm(new sal_Int32[nWidth2]);
std::unique_ptr<sal_Int32[]> pRows(new sal_Int32[nHeight2]);
std::unique_ptr<BitmapColor[]> pColRow1(new BitmapColor[nWidth2]);
std::unique_ptr<BitmapColor[]> pColRow2(new BitmapColor[nWidth2]);
std::unique_ptr<BitmapColor[]> pColRow3(new BitmapColor[nWidth2]);
BitmapColor* pRowTmp1 = pColRow1.get();
BitmapColor* pRowTmp2 = pColRow2.get();
BitmapColor* pRowTmp3 = pColRow3.get();
BitmapColor* pColor;
sal_Int32 nY, nX, i, nSumR, nSumG, nSumB, nMatrixVal, nTmp;
std::array<std::array<sal_Int32, 256>, 9> aKoeff;
sal_Int32* pTmp;
// create LUT of products of matrix value and possible color component values
for (nY = 0; nY < 9; nY++)
{
for (nX = nTmp = 0, nMatrixVal = mrMatrix[nY]; nX < 256; nX++, nTmp += nMatrixVal)
{
aKoeff[nY][nX] = nTmp;
}
}
// create column LUT
for (i = 0; i < nWidth2; i++)
{
pColm[i] = (i > 0) ? (i - 1) : 0;
}
pColm[nWidth + 1] = pColm[nWidth];
// create row LUT
for (i = 0; i < nHeight2; i++)
{
pRows[i] = (i > 0) ? (i - 1) : 0;
}
pRows[nHeight + 1] = pRows[nHeight];
// read first three rows of bitmap color
for (i = 0; i < nWidth2; i++)
{
pColRow1[i] = pReadAcc->GetColor(pRows[0], pColm[i]);
pColRow2[i] = pReadAcc->GetColor(pRows[1], pColm[i]);
pColRow3[i] = pReadAcc->GetColor(pRows[2], pColm[i]);
}
// do convolution
for (nY = 0; nY < nHeight;)
{
Scanline pScanline = pWriteAcc->GetScanline(nY);
for (nX = 0; nX < nWidth; nX++)
{
// first row
pTmp = aKoeff[0].data();
pColor = pRowTmp1 + nX;
nSumR = pTmp[pColor->GetRed()];
nSumG = pTmp[pColor->GetGreen()];
nSumB = pTmp[pColor->GetBlue()];
pTmp = aKoeff[1].data();
nSumR += pTmp[(++pColor)->GetRed()];
nSumG += pTmp[pColor->GetGreen()];
nSumB += pTmp[pColor->GetBlue()];
pTmp = aKoeff[2].data();
nSumR += pTmp[(++pColor)->GetRed()];
nSumG += pTmp[pColor->GetGreen()];
nSumB += pTmp[pColor->GetBlue()];
// second row
pTmp = aKoeff[3].data();
pColor = pRowTmp2 + nX;
nSumR += pTmp[pColor->GetRed()];
nSumG += pTmp[pColor->GetGreen()];
nSumB += pTmp[pColor->GetBlue()];
pTmp = aKoeff[4].data();
nSumR += pTmp[(++pColor)->GetRed()];
nSumG += pTmp[pColor->GetGreen()];
nSumB += pTmp[pColor->GetBlue()];
pTmp = aKoeff[5].data();
nSumR += pTmp[(++pColor)->GetRed()];
nSumG += pTmp[pColor->GetGreen()];
nSumB += pTmp[pColor->GetBlue()];
// third row
pTmp = aKoeff[6].data();
pColor = pRowTmp3 + nX;
nSumR += pTmp[pColor->GetRed()];
nSumG += pTmp[pColor->GetGreen()];
nSumB += pTmp[pColor->GetBlue()];
pTmp = aKoeff[7].data();
nSumR += pTmp[(++pColor)->GetRed()];
nSumG += pTmp[pColor->GetGreen()];
nSumB += pTmp[pColor->GetBlue()];
pTmp = aKoeff[8].data();
nSumR += pTmp[(++pColor)->GetRed()];
nSumG += pTmp[pColor->GetGreen()];
nSumB += pTmp[pColor->GetBlue()];
// calculate destination color
pWriteAcc->SetPixelOnData(
pScanline, nX,
BitmapColor(static_cast<sal_uInt8>(MinMax(nSumR / nDivisor, 0, 255)),
static_cast<sal_uInt8>(MinMax(nSumG / nDivisor, 0, 255)),
static_cast<sal_uInt8>(MinMax(nSumB / nDivisor, 0, 255))));
}
if (++nY < nHeight)
{
if (pRowTmp1 == pColRow1.get())
{
pRowTmp1 = pColRow2.get();
pRowTmp2 = pColRow3.get();
pRowTmp3 = pColRow1.get();
}
else if (pRowTmp1 == pColRow2.get())
{
pRowTmp1 = pColRow3.get();
pRowTmp2 = pColRow1.get();
pRowTmp3 = pColRow2.get();
}
else
{
pRowTmp1 = pColRow1.get();
pRowTmp2 = pColRow2.get();
pRowTmp3 = pColRow3.get();
}
for (i = 0; i < nWidth2; i++)
{
pRowTmp3[i] = pReadAcc->GetColor(pRows[nY + 2], pColm[i]);
}
}
}
pWriteAcc.reset();
bRet = true;
}
pReadAcc.reset();
if (bRet)
{
const MapMode aMap(aBitmap.GetPrefMapMode());
const Size aPrefSize(aBitmap.GetPrefSize());
aBitmap = aNewBmp;
aBitmap.SetPrefMapMode(aMap);
aBitmap.SetPrefSize(aPrefSize);
aKoeff[nY][nX] = nTmp;
}
}
if (bRet)
return BitmapEx(aBitmap);
// create column LUT
for (i = 0; i < nWidth2; i++)
{
pColm[i] = (i > 0) ? (i - 1) : 0;
}
return BitmapEx();
pColm[nWidth + 1] = pColm[nWidth];
// create row LUT
for (i = 0; i < nHeight2; i++)
{
pRows[i] = (i > 0) ? (i - 1) : 0;
}
pRows[nHeight + 1] = pRows[nHeight];
// read first three rows of bitmap color
for (i = 0; i < nWidth2; i++)
{
pColRow1[i] = pReadAcc->GetColor(pRows[0], pColm[i]);
pColRow2[i] = pReadAcc->GetColor(pRows[1], pColm[i]);
pColRow3[i] = pReadAcc->GetColor(pRows[2], pColm[i]);
}
// do convolution
for (nY = 0; nY < nHeight;)
{
Scanline pScanline = pWriteAcc->GetScanline(nY);
for (nX = 0; nX < nWidth; nX++)
{
// first row
pTmp = aKoeff[0].data();
pColor = pRowTmp1 + nX;
nSumR = pTmp[pColor->GetRed()];
nSumG = pTmp[pColor->GetGreen()];
nSumB = pTmp[pColor->GetBlue()];
pTmp = aKoeff[1].data();
nSumR += pTmp[(++pColor)->GetRed()];
nSumG += pTmp[pColor->GetGreen()];
nSumB += pTmp[pColor->GetBlue()];
pTmp = aKoeff[2].data();
nSumR += pTmp[(++pColor)->GetRed()];
nSumG += pTmp[pColor->GetGreen()];
nSumB += pTmp[pColor->GetBlue()];
// second row
pTmp = aKoeff[3].data();
pColor = pRowTmp2 + nX;
nSumR += pTmp[pColor->GetRed()];
nSumG += pTmp[pColor->GetGreen()];
nSumB += pTmp[pColor->GetBlue()];
pTmp = aKoeff[4].data();
nSumR += pTmp[(++pColor)->GetRed()];
nSumG += pTmp[pColor->GetGreen()];
nSumB += pTmp[pColor->GetBlue()];
pTmp = aKoeff[5].data();
nSumR += pTmp[(++pColor)->GetRed()];
nSumG += pTmp[pColor->GetGreen()];
nSumB += pTmp[pColor->GetBlue()];
// third row
pTmp = aKoeff[6].data();
pColor = pRowTmp3 + nX;
nSumR += pTmp[pColor->GetRed()];
nSumG += pTmp[pColor->GetGreen()];
nSumB += pTmp[pColor->GetBlue()];
pTmp = aKoeff[7].data();
nSumR += pTmp[(++pColor)->GetRed()];
nSumG += pTmp[pColor->GetGreen()];
nSumB += pTmp[pColor->GetBlue()];
pTmp = aKoeff[8].data();
nSumR += pTmp[(++pColor)->GetRed()];
nSumG += pTmp[pColor->GetGreen()];
nSumB += pTmp[pColor->GetBlue()];
// calculate destination color
pWriteAcc->SetPixelOnData(
pScanline, nX,
BitmapColor(static_cast<sal_uInt8>(MinMax(nSumR / nDivisor, 0, 255)),
static_cast<sal_uInt8>(MinMax(nSumG / nDivisor, 0, 255)),
static_cast<sal_uInt8>(MinMax(nSumB / nDivisor, 0, 255))));
}
if (++nY < nHeight)
{
if (pRowTmp1 == pColRow1.get())
{
pRowTmp1 = pColRow2.get();
pRowTmp2 = pColRow3.get();
pRowTmp3 = pColRow1.get();
}
else if (pRowTmp1 == pColRow2.get())
{
pRowTmp1 = pColRow3.get();
pRowTmp2 = pColRow1.get();
pRowTmp3 = pColRow2.get();
}
else
{
pRowTmp1 = pColRow1.get();
pRowTmp2 = pColRow2.get();
pRowTmp3 = pColRow3.get();
}
for (i = 0; i < nWidth2; i++)
{
pRowTmp3[i] = pReadAcc->GetColor(pRows[nY + 2], pColm[i]);
}
}
}
pWriteAcc.reset();
pReadAcc.reset();
const MapMode aMap(aBitmap.GetPrefMapMode());
const Size aPrefSize(aBitmap.GetPrefSize());
aBitmap = aNewBmp;
aBitmap.SetPrefMapMode(aMap);
aBitmap.SetPrefSize(aPrefSize);
return BitmapEx(aBitmap);
}
const sal_Int32 g_SharpenMatrix[] = { -1, -1, -1, -1, 16, -1, -1, -1, -1 };
+97 -114
View File
@@ -24,137 +24,120 @@ BitmapEx BitmapEmbossGreyFilter::execute(BitmapEx const& rBitmapEx) const
{
Bitmap aBitmap(rBitmapEx.GetBitmap());
bool bRet = aBitmap.ImplMakeGreyscales();
if (!aBitmap.ImplMakeGreyscales())
return BitmapEx();
if (bRet)
Bitmap::ScopedReadAccess pReadAcc(aBitmap);
if (!pReadAcc)
return BitmapEx();
Bitmap aNewBmp(aBitmap.GetSizePixel(), vcl::PixelFormat::N8_BPP, &pReadAcc->GetPalette());
BitmapScopedWriteAccess pWriteAcc(aNewBmp);
if (!pWriteAcc)
return BitmapEx();
BitmapColor aGrey(sal_uInt8(0));
const sal_Int32 nWidth = pWriteAcc->Width();
const sal_Int32 nHeight = pWriteAcc->Height();
sal_Int32 nGrey11, nGrey12, nGrey13;
sal_Int32 nGrey21, nGrey22, nGrey23;
sal_Int32 nGrey31, nGrey32, nGrey33;
double fAzim = basegfx::deg2rad<100>(mnAzimuthAngle100);
double fElev = basegfx::deg2rad<100>(mnElevationAngle100);
std::unique_ptr<sal_Int32[]> pHMap(new sal_Int32[nWidth + 2]);
std::unique_ptr<sal_Int32[]> pVMap(new sal_Int32[nHeight + 2]);
sal_Int32 nX, nY, nNx, nNy, nDotL;
const sal_Int32 nLx = FRound(cos(fAzim) * cos(fElev) * 255.0);
const sal_Int32 nLy = FRound(sin(fAzim) * cos(fElev) * 255.0);
const sal_Int32 nLz = FRound(sin(fElev) * 255.0);
const auto nZ2 = ((6 * 255) / 4) * ((6 * 255) / 4);
const sal_Int32 nNzLz = ((6 * 255) / 4) * nLz;
const sal_uInt8 cLz = static_cast<sal_uInt8>(std::clamp(nLz, sal_Int32(0), sal_Int32(255)));
// fill mapping tables
pHMap[0] = 0;
for (nX = 1; nX <= nWidth; nX++)
{
bRet = false;
pHMap[nX] = nX - 1;
}
Bitmap::ScopedReadAccess pReadAcc(aBitmap);
pHMap[nWidth + 1] = nWidth - 1;
if (pReadAcc)
pVMap[0] = 0;
for (nY = 1; nY <= nHeight; nY++)
{
pVMap[nY] = nY - 1;
}
pVMap[nHeight + 1] = nHeight - 1;
for (nY = 0; nY < nHeight; nY++)
{
nGrey11 = pReadAcc->GetPixel(pVMap[nY], pHMap[0]).GetIndex();
nGrey12 = pReadAcc->GetPixel(pVMap[nY], pHMap[1]).GetIndex();
nGrey13 = pReadAcc->GetPixel(pVMap[nY], pHMap[2]).GetIndex();
nGrey21 = pReadAcc->GetPixel(pVMap[nY + 1], pHMap[0]).GetIndex();
nGrey22 = pReadAcc->GetPixel(pVMap[nY + 1], pHMap[1]).GetIndex();
nGrey23 = pReadAcc->GetPixel(pVMap[nY + 1], pHMap[2]).GetIndex();
nGrey31 = pReadAcc->GetPixel(pVMap[nY + 2], pHMap[0]).GetIndex();
nGrey32 = pReadAcc->GetPixel(pVMap[nY + 2], pHMap[1]).GetIndex();
nGrey33 = pReadAcc->GetPixel(pVMap[nY + 2], pHMap[2]).GetIndex();
Scanline pScanline = pWriteAcc->GetScanline(nY);
for (nX = 0; nX < nWidth; nX++)
{
Bitmap aNewBmp(aBitmap.GetSizePixel(), vcl::PixelFormat::N8_BPP,
&pReadAcc->GetPalette());
BitmapScopedWriteAccess pWriteAcc(aNewBmp);
nNx = nGrey11 + nGrey21 + nGrey31 - nGrey13 - nGrey23 - nGrey33;
nNy = nGrey31 + nGrey32 + nGrey33 - nGrey11 - nGrey12 - nGrey13;
if (pWriteAcc)
if (!nNx && !nNy)
{
BitmapColor aGrey(sal_uInt8(0));
const sal_Int32 nWidth = pWriteAcc->Width();
const sal_Int32 nHeight = pWriteAcc->Height();
sal_Int32 nGrey11, nGrey12, nGrey13;
sal_Int32 nGrey21, nGrey22, nGrey23;
sal_Int32 nGrey31, nGrey32, nGrey33;
double fAzim = basegfx::deg2rad<100>(mnAzimuthAngle100);
double fElev = basegfx::deg2rad<100>(mnElevationAngle100);
std::unique_ptr<sal_Int32[]> pHMap(new sal_Int32[nWidth + 2]);
std::unique_ptr<sal_Int32[]> pVMap(new sal_Int32[nHeight + 2]);
sal_Int32 nX, nY, nNx, nNy, nDotL;
const sal_Int32 nLx = FRound(cos(fAzim) * cos(fElev) * 255.0);
const sal_Int32 nLy = FRound(sin(fAzim) * cos(fElev) * 255.0);
const sal_Int32 nLz = FRound(sin(fElev) * 255.0);
const auto nZ2 = ((6 * 255) / 4) * ((6 * 255) / 4);
const sal_Int32 nNzLz = ((6 * 255) / 4) * nLz;
const sal_uInt8 cLz
= static_cast<sal_uInt8>(std::clamp(nLz, sal_Int32(0), sal_Int32(255)));
// fill mapping tables
pHMap[0] = 0;
for (nX = 1; nX <= nWidth; nX++)
{
pHMap[nX] = nX - 1;
}
pHMap[nWidth + 1] = nWidth - 1;
pVMap[0] = 0;
for (nY = 1; nY <= nHeight; nY++)
{
pVMap[nY] = nY - 1;
}
pVMap[nHeight + 1] = nHeight - 1;
for (nY = 0; nY < nHeight; nY++)
{
nGrey11 = pReadAcc->GetPixel(pVMap[nY], pHMap[0]).GetIndex();
nGrey12 = pReadAcc->GetPixel(pVMap[nY], pHMap[1]).GetIndex();
nGrey13 = pReadAcc->GetPixel(pVMap[nY], pHMap[2]).GetIndex();
nGrey21 = pReadAcc->GetPixel(pVMap[nY + 1], pHMap[0]).GetIndex();
nGrey22 = pReadAcc->GetPixel(pVMap[nY + 1], pHMap[1]).GetIndex();
nGrey23 = pReadAcc->GetPixel(pVMap[nY + 1], pHMap[2]).GetIndex();
nGrey31 = pReadAcc->GetPixel(pVMap[nY + 2], pHMap[0]).GetIndex();
nGrey32 = pReadAcc->GetPixel(pVMap[nY + 2], pHMap[1]).GetIndex();
nGrey33 = pReadAcc->GetPixel(pVMap[nY + 2], pHMap[2]).GetIndex();
Scanline pScanline = pWriteAcc->GetScanline(nY);
for (nX = 0; nX < nWidth; nX++)
{
nNx = nGrey11 + nGrey21 + nGrey31 - nGrey13 - nGrey23 - nGrey33;
nNy = nGrey31 + nGrey32 + nGrey33 - nGrey11 - nGrey12 - nGrey13;
if (!nNx && !nNy)
{
aGrey.SetIndex(cLz);
}
else if ((nDotL = nNx * nLx + nNy * nLy + nNzLz) < 0)
{
aGrey.SetIndex(0);
}
else
{
const double fGrey
= nDotL / sqrt(static_cast<double>(nNx * nNx + nNy * nNy + nZ2));
aGrey.SetIndex(static_cast<sal_uInt8>(std::clamp(fGrey, 0.0, 255.0)));
}
pWriteAcc->SetPixelOnData(pScanline, nX, aGrey);
if (nX < (nWidth - 1))
{
const sal_Int32 nNextX = pHMap[nX + 3];
nGrey11 = nGrey12;
nGrey12 = nGrey13;
nGrey13 = pReadAcc->GetPixel(pVMap[nY], nNextX).GetIndex();
nGrey21 = nGrey22;
nGrey22 = nGrey23;
nGrey23 = pReadAcc->GetPixel(pVMap[nY + 1], nNextX).GetIndex();
nGrey31 = nGrey32;
nGrey32 = nGrey33;
nGrey33 = pReadAcc->GetPixel(pVMap[nY + 2], nNextX).GetIndex();
}
}
}
pHMap.reset();
pVMap.reset();
pWriteAcc.reset();
bRet = true;
aGrey.SetIndex(cLz);
}
else if ((nDotL = nNx * nLx + nNy * nLy + nNzLz) < 0)
{
aGrey.SetIndex(0);
}
else
{
const double fGrey = nDotL / sqrt(static_cast<double>(nNx * nNx + nNy * nNy + nZ2));
aGrey.SetIndex(static_cast<sal_uInt8>(std::clamp(fGrey, 0.0, 255.0)));
}
pReadAcc.reset();
pWriteAcc->SetPixelOnData(pScanline, nX, aGrey);
if (bRet)
if (nX < (nWidth - 1))
{
const MapMode aMap(aBitmap.GetPrefMapMode());
const Size aPrefSize(aBitmap.GetPrefSize());
const sal_Int32 nNextX = pHMap[nX + 3];
aBitmap = aNewBmp;
aBitmap.SetPrefMapMode(aMap);
aBitmap.SetPrefSize(aPrefSize);
nGrey11 = nGrey12;
nGrey12 = nGrey13;
nGrey13 = pReadAcc->GetPixel(pVMap[nY], nNextX).GetIndex();
nGrey21 = nGrey22;
nGrey22 = nGrey23;
nGrey23 = pReadAcc->GetPixel(pVMap[nY + 1], nNextX).GetIndex();
nGrey31 = nGrey32;
nGrey32 = nGrey33;
nGrey33 = pReadAcc->GetPixel(pVMap[nY + 2], nNextX).GetIndex();
}
}
}
if (bRet)
return BitmapEx(aBitmap);
pHMap.reset();
pVMap.reset();
pWriteAcc.reset();
pReadAcc.reset();
return BitmapEx();
const MapMode aMap(aBitmap.GetPrefMapMode());
const Size aPrefSize(aBitmap.GetPrefSize());
aBitmap = aNewBmp;
aBitmap.SetPrefMapMode(aMap);
aBitmap.SetPrefSize(aPrefSize);
return BitmapEx(aBitmap);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+60 -67
View File
@@ -1179,83 +1179,76 @@ static Bitmap DetectEdges( const Bitmap& rBmp )
{
constexpr sal_uInt8 cEdgeDetectThreshold = 128;
const Size aSize( rBmp.GetSizePixel() );
Bitmap aRetBmp;
if( ( aSize.Width() > 2 ) && ( aSize.Height() > 2 ) )
if( ( aSize.Width() <= 2 ) || ( aSize.Height() <= 2 ) )
return rBmp;
Bitmap aWorkBmp( rBmp );
if( !aWorkBmp.Convert( BmpConversion::N8BitGreys ) )
return rBmp;
ScopedVclPtr<VirtualDevice> pVirDev(VclPtr<VirtualDevice>::Create());
pVirDev->SetOutputSizePixel(aSize);
Bitmap::ScopedReadAccess pReadAcc(aWorkBmp);
if( !pReadAcc )
return rBmp;
const tools::Long nWidth = aSize.Width();
const tools::Long nWidth2 = nWidth - 2;
const tools::Long nHeight = aSize.Height();
const tools::Long nHeight2 = nHeight - 2;
const tools::Long lThres2 = static_cast<tools::Long>(cEdgeDetectThreshold) * cEdgeDetectThreshold;
tools::Long nSum1;
tools::Long nSum2;
tools::Long lGray;
// initialize border with white pixels
pVirDev->SetLineColor( COL_WHITE );
pVirDev->DrawLine( Point(), Point( nWidth - 1, 0L ) );
pVirDev->DrawLine( Point( nWidth - 1, 0L ), Point( nWidth - 1, nHeight - 1 ) );
pVirDev->DrawLine( Point( nWidth - 1, nHeight - 1 ), Point( 0L, nHeight - 1 ) );
pVirDev->DrawLine( Point( 0, nHeight - 1 ), Point() );
for( tools::Long nY = 0, nY1 = 1, nY2 = 2; nY < nHeight2; nY++, nY1++, nY2++ )
{
Bitmap aWorkBmp( rBmp );
if( aWorkBmp.Convert( BmpConversion::N8BitGreys ) )
Scanline pScanlineRead = pReadAcc->GetScanline( nY );
Scanline pScanlineRead1 = pReadAcc->GetScanline( nY1 );
Scanline pScanlineRead2 = pReadAcc->GetScanline( nY2 );
for( tools::Long nX = 0, nXDst = 1, nXTmp; nX < nWidth2; nX++, nXDst++ )
{
bool bRet = false;
nXTmp = nX;
ScopedVclPtr<VirtualDevice> pVirDev(VclPtr<VirtualDevice>::Create());
pVirDev->SetOutputSizePixel(aSize);
Bitmap::ScopedReadAccess pReadAcc(aWorkBmp);
nSum2 = pReadAcc->GetIndexFromData( pScanlineRead, nXTmp++ );
nSum1 = -nSum2;
nSum2 += static_cast<tools::Long>(pReadAcc->GetIndexFromData( pScanlineRead, nXTmp++ )) << 1;
lGray = pReadAcc->GetIndexFromData( pScanlineRead, nXTmp );
nSum1 += lGray;
nSum2 += lGray;
if( pReadAcc )
{
const tools::Long nWidth = aSize.Width();
const tools::Long nWidth2 = nWidth - 2;
const tools::Long nHeight = aSize.Height();
const tools::Long nHeight2 = nHeight - 2;
const tools::Long lThres2 = static_cast<tools::Long>(cEdgeDetectThreshold) * cEdgeDetectThreshold;
tools::Long nSum1;
tools::Long nSum2;
tools::Long lGray;
nSum1 += static_cast<tools::Long>(pReadAcc->GetIndexFromData( pScanlineRead1, nXTmp )) << 1;
nXTmp -= 2;
nSum1 -= static_cast<tools::Long>(pReadAcc->GetIndexFromData( pScanlineRead1, nXTmp )) << 1;
// initialize border with white pixels
pVirDev->SetLineColor( COL_WHITE );
pVirDev->DrawLine( Point(), Point( nWidth - 1, 0L ) );
pVirDev->DrawLine( Point( nWidth - 1, 0L ), Point( nWidth - 1, nHeight - 1 ) );
pVirDev->DrawLine( Point( nWidth - 1, nHeight - 1 ), Point( 0L, nHeight - 1 ) );
pVirDev->DrawLine( Point( 0, nHeight - 1 ), Point() );
lGray = -static_cast<tools::Long>(pReadAcc->GetIndexFromData( pScanlineRead2, nXTmp++ ));
nSum1 += lGray;
nSum2 += lGray;
nSum2 -= static_cast<tools::Long>(pReadAcc->GetIndexFromData( pScanlineRead2, nXTmp++ )) << 1;
lGray = static_cast<tools::Long>(pReadAcc->GetIndexFromData( pScanlineRead2, nXTmp ));
nSum1 += lGray;
nSum2 -= lGray;
for( tools::Long nY = 0, nY1 = 1, nY2 = 2; nY < nHeight2; nY++, nY1++, nY2++ )
{
Scanline pScanlineRead = pReadAcc->GetScanline( nY );
Scanline pScanlineRead1 = pReadAcc->GetScanline( nY1 );
Scanline pScanlineRead2 = pReadAcc->GetScanline( nY2 );
for( tools::Long nX = 0, nXDst = 1, nXTmp; nX < nWidth2; nX++, nXDst++ )
{
nXTmp = nX;
nSum2 = pReadAcc->GetIndexFromData( pScanlineRead, nXTmp++ );
nSum1 = -nSum2;
nSum2 += static_cast<tools::Long>(pReadAcc->GetIndexFromData( pScanlineRead, nXTmp++ )) << 1;
lGray = pReadAcc->GetIndexFromData( pScanlineRead, nXTmp );
nSum1 += lGray;
nSum2 += lGray;
nSum1 += static_cast<tools::Long>(pReadAcc->GetIndexFromData( pScanlineRead1, nXTmp )) << 1;
nXTmp -= 2;
nSum1 -= static_cast<tools::Long>(pReadAcc->GetIndexFromData( pScanlineRead1, nXTmp )) << 1;
lGray = -static_cast<tools::Long>(pReadAcc->GetIndexFromData( pScanlineRead2, nXTmp++ ));
nSum1 += lGray;
nSum2 += lGray;
nSum2 -= static_cast<tools::Long>(pReadAcc->GetIndexFromData( pScanlineRead2, nXTmp++ )) << 1;
lGray = static_cast<tools::Long>(pReadAcc->GetIndexFromData( pScanlineRead2, nXTmp ));
nSum1 += lGray;
nSum2 -= lGray;
if( ( nSum1 * nSum1 + nSum2 * nSum2 ) < lThres2 )
pVirDev->DrawPixel( Point(nXDst, nY), COL_WHITE );
else
pVirDev->DrawPixel( Point(nXDst, nY), COL_BLACK );
}
}
bRet = true;
}
pReadAcc.reset();
if( bRet )
aRetBmp = pVirDev->GetBitmap(Point(0,0), aSize);
if( ( nSum1 * nSum1 + nSum2 * nSum2 ) < lThres2 )
pVirDev->DrawPixel( Point(nXDst, nY), COL_WHITE );
else
pVirDev->DrawPixel( Point(nXDst, nY), COL_BLACK );
}
}
pReadAcc.reset();
Bitmap aRetBmp = pVirDev->GetBitmap(Point(0,0), aSize);
if( aRetBmp.IsEmpty() )
aRetBmp = rBmp;
else