Blur only an image border?

I would like to add a blurred border to an Image. So, if I have a 1024x1024 image, the outermost 8px of the image would be blurred. What is the best way to do this in JUCE?

Currently I am making a copy of the image, downsizing it, applying the blur, scaling back up and then overlaying the original image on top.

But this seems overly complicated an inefficient. What would be useful is if I could apply a mask and blur the non-masked region.

Possible?

I haven’t tried it myself, but blurring can be done with the Gaussian convolution. There is the ImageConvolutionKernel class available for it, and if you specify the border areas, it should do what you want.

Thanks @Daniel. ImageConvolutionKernel is what I’m already using.

The relevant method signature is:

@param destinationArea the region of the image to apply the filter to

void applyToImage (Image& destImage,
                           const Image& sourceImage,
                           const Rectangle<int>& destinationArea) const 

I’m looking for kind of the opposite of destinationArea. So, apply the filter only to the area outside the destinationArea. Like this:

blur

I see what you mean, my idea was to apply the convolution only on the border places:

    const auto loaded = ImageCache::getFromFile (File::getSpecialLocation(File::userPicturesDirectory).getChildFile ("Mietzi.jpg")).rescaled (1024, 768);
    image = loaded.createCopy();

    auto borderWidth = std::min (image.getWidth(), image.getHeight()) * 0.1f;

    auto bounds = image.getBounds();
    ImageConvolutionKernel gauss (15);
    gauss.createGaussianBlur (7.0f);
    gauss.applyToImage (image, loaded, bounds.removeFromTop (borderWidth));
    gauss.applyToImage (image, loaded, bounds.removeFromBottom (borderWidth));
    gauss.applyToImage (image, loaded, bounds.withWidth (borderWidth));
    gauss.applyToImage (image, loaded, bounds.withX (bounds.getRight() - borderWidth));

If you do that in place, you get artefacts, but if you get the input pixels from a copy, it looks ok to me.

An alternative is to run the filter and copy the unblurred part into, which is a bit of a waste.

2 Likes

Ah Thanks… I don’t know why I didn’t think of that!

However… it unfortunately doesn’t give the speedup I’d hoped for. I’ve also tried shrinking down the image, applying the blur then scaling back up, but this introduces even more overhead.

It seems like JUCE’s blurring and rescaling are both quite slow, so my best option is probably going to be to pre-render these effects.

Yes, I was also amazed, how slow the convolution works.
First I had the image with the original 4592x3448, I couldn’t bring up the patience until it finishes…

Looking at the implementation of applyToImage(), I think there is room for improvement.
But rendering only once in advance makes perfectly sense to me.

1 Like