Jump to content

Question about layer mode overlay


refar32
 Share

Recommended Posts

I'm not planning on developing a full-fledged Paint.NET effect, so I hope it's ok to ask this here anyway.

Otherwise I apologize and ask for the thread to be moved where it belongs.

I'm currently in the process of developing a little tool in C#. It's really only a small utility to merge pictures of fixed sizes in a specific way. Nothing fancy at all.

I have very little experience in picture processing, so I'm no expert nor do I aim to get one anytime soon.

The tool I've written already works as intended, but I'd like to add a functionality to it that's supposed to work like the overlay layer mode, but I have no idea how that exactly works.

I know how to process images in principle, and obviously I'll have to do something with each overlaid pixel.

Could anyone, in simple terms, explain what it does? Such as, takes the highest Green value from both pictures, or adds half the Red value from picture A to that of picture B ... obviously these examples are nonsense in this context, but I'd like to know what I need to do in a similar manner.

Otherwise, I downloaded an older version of Paint.NET - maybe someone can point out in which of the source files the blending takes place, then I could look it up there.

Thank you very much in advance.

-Refar

Link to comment
Share on other sites

This is the macro that implements the Overlay blending mode,

#define INT_SCALE_MULT(a,  ((a) * ( + 0x80)
#define INT_SCALE_DIV(r) ((((r) >> 8) + (r)) >> 8)
#define INT_SCALE(a, b, r) { (r) = INT_SCALE_MULT((a), (); (r) = INT_SCALE_DIV((r)); }

#define BLENDMODE_OVERLAY(A, B, r) \
{ \
if ((A) < 128) \
{ \
	INT_SCALE(2 * (A), (, r); \
} \
else \
{ \
	INT_SCALE(2 * (255 - (A)), 255 - (, r); \
	r = 255 - r; \
} \
}

A and B are color components, e.g. one of Red, Green, or Blue from either the "under" (A) or the "over" (B) layer's pixel. The macro is run once for each R, G, B, and then a standard bit of code is always run for the alpha channel.

"r" is the result (think of it as "return"). The syntax is weird because of the use of C++'s preprocessor being borrowed for the use of C# code generation.

INT_SCALE takes two integers in the range (0,255) and then computes ( a * b ) / 255. Basically, pretend they are numbers in the range [0,1] and multiply them to get a new number in the pretend-range [0, 1].

I've got to run, so you'll have to figure out any further meaning on your own ...

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

I'm honored to receive a reply from the master of Paint.NET in person, thank you very much Rick.

I tried to recreate that snippet how I understood it as best I could ... and it ALMOST does what I want it to do - except it doesn't work correctly on ALL pixels.

Probably some wee little error someplace ... but I can't find it.

Here's what I made of the code you provided:

 	
private int scaleMult(int a, int 
{
	return ((a) * ( + 0x80);
}

private int scaleDiv(int r)
{
	return ((((r) >> 8) + (r)) >> 8);
}

private int scale(int a, int 
{
	int r = scaleMult((a), ();
	r = scaleDiv(r);
	return r;
}

private int blend(int a, int 
{
	int retVal;
	if (a < 128)
	{
	retVal = scale(2 * a, ;
	}
	else
	{
// This was the line with the error
	//retVal = scale(255 - a, 255 - ;
retVal = scale(2*(255 - a), 255 - ;
	retVal = 255 - retVal;
	}
	return retVal;
}

What's my OBVIOUS mistake?

Thank you very much in advance.

Edit: Proof to the idea that sometimes just writing down your problem brings you closer to the solution.

Simple error, I forgot to add the 2* multiplier before one calculation. Doh!

Now it works perfectly, thank you SO much for your help Rick.

I corrected the snippet so it works, should anyone else ever stumble across this, he'll have a working code to copy/paste.

-Refar

Edited by refar32
Link to comment
Share on other sites

And if you're wondering why I use code generation for these, consider that the macro listed above expands out to this, most of which is common to all the blend ops.

public override ColorBgra Apply(ColorBgra lhs, ColorBgra rhs)
{
int fB;
int fG;
int fR;
ColorBgra ret = new ColorBgra();
int lhsA = lhs.A;
int rhsA = rhs.A;
int y = (lhsA * (0xff - rhsA)) + 0x80;
y = ((y >> 8) + y) >> 8;
int totalA = y + rhsA;
if (totalA == 0)
{
	ret.Bgra = 0;
	return ret;
}
if (lhs.B < 0x80)
{
	fB = ((2 * lhs. * rhs. + 0x80;
	fB = ((fB >> 8) + fB) >> 8;
}
else
{
	fB = ((2 * (0xff - lhs.) * (0xff - rhs.) + 0x80;
	fB = ((fB >> 8) + fB) >> 8;
	fB = 0xff - fB;
}
if (lhs.G < 0x80)
{
	fG = ((2 * lhs.G) * rhs.G) + 0x80;
	fG = ((fG >> 8) + fG) >> 8;
}
else
{
	fG = ((2 * (0xff - lhs.G)) * (0xff - rhs.G)) + 0x80;
	fG = ((fG >> 8) + fG) >> 8;
	fG = 0xff - fG;
}
if (lhs.R < 0x80)
{
	fR = ((2 * lhs.R) * rhs.R) + 0x80;
	fR = ((fR >> 8) + fR) >> 8;
}
else
{
	fR = ((2 * (0xff - lhs.R)) * (0xff - rhs.R)) + 0x80;
	fR = ((fR >> 8) + fR) >> 8;
	fR = 0xff - fR;
}
int x = (lhsA * rhsA) + 0x80;
x = ((x >> 8) + x) >> 8;
int z = rhsA - x;
int masIndex = totalA * 3;
uint taM = CompositionOps.masTable[masIndex];
uint taA = CompositionOps.masTable[masIndex + 1];
uint taS = CompositionOps.masTable[masIndex + 2];
uint b = (uint) ((((((lhs.B * y) + (rhs.B * z)) + (fB * x)) * taM) + taA) >> taS);
uint g = (uint) ((((((lhs.G * y) + (rhs.G * z)) + (fG * x)) * taM) + taA) >> taS);
uint r = (uint) ((((((lhs.R * y) + (rhs.R * z)) + (fR * x)) * taM) + taA) >> taS);
int a = (lhsA * (0xff - rhsA)) + 0x80;
a = ((a >> 8) + a) >> 8;
a += rhsA;
ret.Bgra = ((b | (g << 8)) | (r << 0x10)) | ((uint) (a << 0x18));
return ret;
}

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...