Custom blend modes

Questions and postings pertaining to the development of ImageMagick, feature enhancements, and ImageMagick internals. ImageMagick source code and algorithms are discussed here. Usage questions which are too arcane for the normal user list should also be posted here.
Post Reply
aidynskas

Custom blend modes

Post by aidynskas »

Hi,

I'm totally stuck trying to implement Photoshop blending modes. There is a great website with all of the blending modes explained: http://www.simplefilter.de/en/grundlagen/mixmods.html

For example I tried to implement the Linear Light blending mode. Here is a code snippet from my LinearLight method (it is called by CompositeLinearLight, which is just a copy/paste of existing composite ops in ImageMagick):

Linear Light formula: C=B+2*A-1, where C=result B=destination pixel A=source pixel and A,B,C are all in [0;1] range.

Code: Select all

pixel=(((1.0-QuantumScale*beta)*q*QuantumScale)+2*((1.0-QuantumScale*alpha)*p*QuantumScale)-1.0)*QuantumRange+(1.0-QuantumScale*alpha)*p*QuantumScale*beta+(1.0-QuantumScale*beta)*q*
    QuantumScale*alpha;

Code: Select all

(((1.0-QuantumScale*beta)*q*QuantumScale)+2*((1.0-QuantumScale*alpha)*p*QuantumScale)-1.0)*QuantumRange
part is the actual foruma from the website and the rest is an attempt to blend the result correctly.

This snipped is based on the existing Multiply composite op in ImageMagick. Unfortunately the result is totally wrong. I believe something is wrong with the blending of the result, but I just have no idea what. Anyone could help me by writing an example of how the blend modes should be written in ImageMagic? I would gladly implement the rest of them and submit a patch.

Thank you!
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Custom blend modes

Post by magick »

Try this and let us know if it works:

Code: Select all

static inline MagickRealType LinearLight(const MagickRealType p,
  const MagickRealType alpha,const MagickRealType q,const MagickRealType beta)
{ 
  return((1.0-QuantumScale*beta)*q+2.0*(1.0-QuantumScale*alpha)*p-1.0);
}

static inline void CompositeLinearLight(const MagickPixelPacket *p,
  const MagickRealType alpha,const MagickPixelPacket *q,
  const MagickRealType beta,MagickPixelPacket *composite)
{
  MagickRealType
    gamma;

  gamma=RoundToUnity((1.0-QuantumScale*alpha)-(1.0-QuantumScale*beta));
  composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
  gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
  composite->red=gamma*LinearLight(p->red,alpha,q->red,beta);
  composite->green=gamma*LinearLight(p->green,alpha,q->green,beta);
  composite->blue=gamma*LinearLight(p->blue,alpha,q->blue,beta);
  if (q->colorspace == CMYKColorspace)
    composite->index=gamma*LinearLight(p->index,alpha,q->index,beta);
}   
aidynskas

Re: Custom blend modes

Post by aidynskas »

Unfortunately it didn't work.

I've tried your original and a little modified version (the -1.0 changed to -QuantumRange):

Code: Select all

static inline MagickRealType LinearLight(const MagickRealType p,
  const MagickRealType alpha,const MagickRealType q,const MagickRealType beta)
{ 
  return((1.0-QuantumScale*beta)*q+2.0*(1.0-QuantumScale*alpha)*p-QuantumRange);
}
I've also tried to change your

Code: Select all

gamma=RoundToUnity((1.0-QuantumScale*alpha)-(1.0-QuantumScale*beta));
to:

Code: Select all

gamma=RoundToUnity((1.0-QuantumScale*alpha)+(1.0-QuantumScale*beta)-(1.0-QuantumScale*alpha)*(1.0-QuantumScale*beta));
And this one combined with -QuantumRange fix gave me correct result in the areas where both the destination and source images overlaped and their alpha values were 1.0, while the areas that didn't overlap were blended incorrectly (no blending should occur in the areas where destination alpha is 0.0).

The plain C=B+2*A-1 formula seems to be correct when both the destination and source pixels are opaque, but I am totally confused how the destination and source pixels should blend if they aren't. I could post some before/after test pictures from Photoshop if that would help.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Custom blend modes

Post by magick »

Doh! The gamma should be
  • gamma=RoundToUnity((1.0-QuantumScale*beta)+2.0*(1.0-QuantumScale*alpha)-1.0)
That is a literal translation of the formula given. Whether it works or not is another matter.
Post Reply