mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
ImageConvolutionKernel: Refactor and fix bugs in single-channel convolution
This commit is contained in:
parent
90f37570f3
commit
fae3e2c010
1 changed files with 35 additions and 131 deletions
|
|
@ -42,9 +42,7 @@ ImageConvolutionKernel::ImageConvolutionKernel (int sizeToUse)
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageConvolutionKernel::~ImageConvolutionKernel()
|
ImageConvolutionKernel::~ImageConvolutionKernel() = default;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
float ImageConvolutionKernel::getKernelValue (const int x, const int y) const noexcept
|
float ImageConvolutionKernel::getKernelValue (const int x, const int y) const noexcept
|
||||||
|
|
@ -144,8 +142,10 @@ void ImageConvolutionKernel::applyToImage (Image& destImage,
|
||||||
|
|
||||||
const Image::BitmapData srcData (sourceImage, Image::BitmapData::readOnly);
|
const Image::BitmapData srcData (sourceImage, Image::BitmapData::readOnly);
|
||||||
|
|
||||||
if (destData.pixelStride == 4)
|
const auto applyKernel = [&] (auto stride)
|
||||||
{
|
{
|
||||||
|
constexpr auto pixelStride = stride.value;
|
||||||
|
|
||||||
for (int y = area.getY(); y < bottom; ++y)
|
for (int y = area.getY(); y < bottom; ++y)
|
||||||
{
|
{
|
||||||
uint8* dest = line;
|
uint8* dest = line;
|
||||||
|
|
@ -153,10 +153,7 @@ void ImageConvolutionKernel::applyToImage (Image& destImage,
|
||||||
|
|
||||||
for (int x = area.getX(); x < right; ++x)
|
for (int x = area.getX(); x < right; ++x)
|
||||||
{
|
{
|
||||||
float c1 = 0;
|
float sum[pixelStride]{};
|
||||||
float c2 = 0;
|
|
||||||
float c3 = 0;
|
|
||||||
float c4 = 0;
|
|
||||||
|
|
||||||
for (int yy = 0; yy < size; ++yy)
|
for (int yy = 0; yy < size; ++yy)
|
||||||
{
|
{
|
||||||
|
|
@ -165,140 +162,47 @@ void ImageConvolutionKernel::applyToImage (Image& destImage,
|
||||||
if (sy >= srcData.height)
|
if (sy >= srcData.height)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (sy >= 0)
|
if (sy < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int sx = x - (size >> 1);
|
||||||
|
const uint8* src = srcData.getPixelPointer (sx, sy);
|
||||||
|
|
||||||
|
for (int xx = 0; xx < size; ++xx)
|
||||||
{
|
{
|
||||||
int sx = x - (size >> 1);
|
if (sx >= srcData.width)
|
||||||
const uint8* src = srcData.getPixelPointer (sx, sy);
|
break;
|
||||||
|
|
||||||
for (int xx = 0; xx < size; ++xx)
|
if (sx >= 0)
|
||||||
{
|
{
|
||||||
if (sx >= srcData.width)
|
const auto kernelMult = values[xx + yy * size];
|
||||||
break;
|
|
||||||
|
|
||||||
if (sx >= 0)
|
for (auto& s : sum)
|
||||||
{
|
s += kernelMult * *src++;
|
||||||
const float kernelMult = values [xx + yy * size];
|
|
||||||
c1 += kernelMult * *src++;
|
|
||||||
c2 += kernelMult * *src++;
|
|
||||||
c3 += kernelMult * *src++;
|
|
||||||
c4 += kernelMult * *src++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
src += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
++sx;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
src += pixelStride;
|
||||||
|
}
|
||||||
|
|
||||||
|
++sx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*dest++ = (uint8) jmin (0xff, roundToInt (c1));
|
for (const auto& s : sum)
|
||||||
*dest++ = (uint8) jmin (0xff, roundToInt (c2));
|
*dest++ = (uint8) jmin (0xff, roundToInt (s));
|
||||||
*dest++ = (uint8) jmin (0xff, roundToInt (c3));
|
|
||||||
*dest++ = (uint8) jmin (0xff, roundToInt (c4));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
else if (destData.pixelStride == 3)
|
|
||||||
|
switch (destData.pixelStride)
|
||||||
{
|
{
|
||||||
for (int y = area.getY(); y < bottom; ++y)
|
case 4:
|
||||||
{
|
return applyKernel (std::integral_constant<size_t, 4>{});
|
||||||
uint8* dest = line;
|
case 3:
|
||||||
line += destData.lineStride;
|
return applyKernel (std::integral_constant<size_t, 3>{});
|
||||||
|
case 1:
|
||||||
for (int x = area.getX(); x < right; ++x)
|
return applyKernel (std::integral_constant<size_t, 1>{});
|
||||||
{
|
|
||||||
float c1 = 0;
|
|
||||||
float c2 = 0;
|
|
||||||
float c3 = 0;
|
|
||||||
|
|
||||||
for (int yy = 0; yy < size; ++yy)
|
|
||||||
{
|
|
||||||
const int sy = y + yy - (size >> 1);
|
|
||||||
|
|
||||||
if (sy >= srcData.height)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (sy >= 0)
|
|
||||||
{
|
|
||||||
int sx = x - (size >> 1);
|
|
||||||
const uint8* src = srcData.getPixelPointer (sx, sy);
|
|
||||||
|
|
||||||
for (int xx = 0; xx < size; ++xx)
|
|
||||||
{
|
|
||||||
if (sx >= srcData.width)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (sx >= 0)
|
|
||||||
{
|
|
||||||
const float kernelMult = values [xx + yy * size];
|
|
||||||
c1 += kernelMult * *src++;
|
|
||||||
c2 += kernelMult * *src++;
|
|
||||||
c3 += kernelMult * *src++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
src += 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
++sx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*dest++ = (uint8) roundToInt (c1);
|
|
||||||
*dest++ = (uint8) roundToInt (c2);
|
|
||||||
*dest++ = (uint8) roundToInt (c3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (destData.pixelStride == 1)
|
|
||||||
{
|
|
||||||
for (int y = area.getY(); y < bottom; ++y)
|
|
||||||
{
|
|
||||||
uint8* dest = line;
|
|
||||||
line += destData.lineStride;
|
|
||||||
|
|
||||||
for (int x = area.getX(); x < right; ++x)
|
|
||||||
{
|
|
||||||
float c1 = 0;
|
|
||||||
|
|
||||||
for (int yy = 0; yy < size; ++yy)
|
|
||||||
{
|
|
||||||
const int sy = y + yy - (size >> 1);
|
|
||||||
|
|
||||||
if (sy >= srcData.height)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (sy >= 0)
|
|
||||||
{
|
|
||||||
int sx = x - (size >> 1);
|
|
||||||
const uint8* src = srcData.getPixelPointer (sx, sy);
|
|
||||||
|
|
||||||
for (int xx = 0; xx < size; ++xx)
|
|
||||||
{
|
|
||||||
if (sx >= srcData.width)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (sx >= 0)
|
|
||||||
{
|
|
||||||
const float kernelMult = values [xx + yy * size];
|
|
||||||
c1 += kernelMult * *src++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
src += 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
++sx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*dest++ = (uint8) roundToInt (c1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue