More image Blending modes?

hi,

Is there any chance that we can have other blending modes like Overlay, Multiply, Screen mode, XOR,… etc?

some links summarizing the definitions:
http://www.w3.org/TR/2002/WD-SVG11-20020215/masking.html

http://doc.trolltech.com/4.3/qpainter.html#CompositionMode-enum

http://www.cairographics.org/operators/

http://www.svgopen.org/2005/papers/abstractsvgopen/

http://keithp.com/~keithp/porterduff/p253-porter.pdf

1 Like

Well not in the near future… Those things are very time-consuming to write!

I guess adding the necessary functions in PixelARGB and PixelRGB is just the easy part of this. Tracking every places is the codebase that needs to be modified is another story.

Anyway, if you need people to help, just ask. I bet I wouldn’t be the only one to contribute.

Thanks. At the moment though, I really need to concentrate on getting through some of the stuff that’s already on my to-do-list before I start adding even more to it!

ok understand,

In the meantime, do you have anything better than that to suggest

[code]Image *dst = createComponentSnapshot(g.getClipBounds(), true);

Image src(Image::ARGB, getWidth(), getHeight(), true);
Graphics gfx(&src);

// draw within gfx

blendImages(*dst, src, BlendingModes::Overlay);

g.drawImage(dst, 0, 0, getWidth(), getHeight(), 0, 0, getWidth(), getHeight());

delete dst;
[/code]

I guess that’d work fine, though it’s a bit inefficient. To do better, you’d need to extend your own LowLevelGraphicContext object, which would be a bit of a pain.

this was a thing i asked for long time ago, but never had time to start digging into.

anyway you could look in the LowLevelGraphicaSoftwareRenderer:

template <class DestPixelType, class SrcPixelType> static void transformedImageRender (Image& destImage, const Image& sourceImage, const int destClipX, const int destClipY, const int destClipW, const int destClipH, const int srcClipX, const int srcClipY, const int srcClipWidth, const int srcClipHeight, double srcX, double srcY, const double lineDX, const double lineDY, const double pixelDX, const double pixelDY, const uint8 alpha, const Graphics::ResamplingQuality quality, DestPixelType*, SrcPixelType*)

this one is the “hot spot” where every image blending function calls (or maybe i’m wrong… jules?). below, you can find the line where it do:

for every pixel. try to write xor, burn, and so on function for the pixel types and then replace the blend with another one. that could be a start just to check if it will work. adding a parameter to that function (specifying a blend mode), then recurse out and parameterize all the other image drawing functions could be straightforward (while maintaining backwards compatibility in the Graphics class).

the only problem could be the path/gradient function filled with images, but they could already rely on transformedImageRender, i don’t know.

anyway if you need some human power to dig into this, i can give as much help as i can !

hi,

I’ve written most of the pixel blending modes defined in the link above and I’ve made a little demo application to test them.

http://mdsp.smartelectronix.com/juce/PixelBlending.zip

there’s a file called juce_PixelBlenders.h (which I hope could end beside juce_PixelFormats.h) Which defines a struct like this one for each blending mode:

struct JUCE_API DefaultPixelBlender { template <class Pixel1, class Pixel2> static forcedinline void blend(Pixel1 &dst, const Pixel2& src) { dst.blend(src); } };

I’ve also written a quick image blending function which takes a template PixelBlender argument

[code]template
inline void BlendPixel(PixelARGB &dst, const PixelARGB &src)
{
PixelBlender blender;
blender.blend(dst, src);
}

template
static void BlendRow(PixelARGB *dst, const PixelARGB *src, int numPixels);

template
static void Blend(Image &dstImage, const Image& srcImage);[/code]

and here’s the result:

I’m not sure it’s 100% correct (especially the very last ones), but most of them are.

Hope it will help push it into juce… :slight_smile:

1 Like

Cool. Does it handle alpha values correctly?

almost…

the following image uses 2 gradients:

  • blue->transparent blue
  • yellow -> transparent yellow

instead of triangles

clearly there’s something wrong with SrcOut, Plus, Overlay and Lighten

mostly because of int arithmetic. we have to be very careful with overflow and wraparound here

I’ve uploaded a new version with some fixes

http://mdsp.smartelectronix.com/juce/PixelBlending.zip

and some more blending modes:

with gradient, transparency, triangle areas, and checkboard background

1 Like

Mdsp, this looks really, really cool!

Great job!

the hardest part remains to be done though, i.e. adding Graphics::setBlendingMode and modifying every place where a blending occur accordingly.

However in the short term, adding variants of Graphics::drawImage* with an additional blending operator could be done quickly.

so that you could do

Image img(Image::ARGB, getWidth(), getHeight());
Graphics gfx(img);

// draw into img using gfx

g.drawAt(0, 0, &img, BlendingModes::Overlay);

That should be enough to solve most people needs as long as you don’t mix a lot of layers and blending modes since it requires you to create an Image for each.

Sorry for upping this thread, but any news about blending modes? is it still far from being atop the todo list?

3 Likes

Sorry, very low on our priority list! Would be a lot of hassle to do this because it’d need adding to all the renderers, which would be a lot of work, and it’s a feature that very few people would use.