Closed G-e-n-e-v-e-n-s-i-S closed 3 months ago
Workaround if the images that must be blended are known:
linear_blend
linear_blend
set_mask
function to bake the blended alpha channels back into the blended imagesThe source for linear blend is here I believe. https://github.com/haganbmj/MagicSetEditor2/blob/ddd49b50d7d947e4451d31243ea29d7778c16884/src/gfx/blend_image.cpp#L18-L59
I don't really know the math behind all this, but I know transparency in general is a weak point with MSE. I think it treats most things internally as jpg?
Okay, so I don't know c++, so I'm kind of flailing like a headless chicken here, but looking at this other file, it seems it's not forgetting the alpha (it says it right there in the comment!):
So maybe adapting this to here would give something like this, to be added at the end of what you linked:
if (img1.HasAlpha() && img2.HasAlpha()) {
data1 = img1.GetAlpha();
data2 = img2.GetAlpha();
for (int y = 0 ; y < height ; ++y) {
for (int x = 0 ; x < width ; ++x) {
int mult = x * xm + y * ym + d;
if (mult < 0) mult = 0;
if (mult > fixed) mult = fixed;
data1[0] = data1[0] + mult * (data2[0] - data1[0]) / fixed;
data1 += 1;
data2 += 1;
}
}
}
That appears to work, nice work inferring that. I'm going to poke around and see if I can spot anything that breaks.
I'm not sure what masked_blend
should look like, never used these functions before.
Took a stab at it, but not sure it's the right approach.
https://github.com/haganbmj/MagicSetEditor2/pull/83
The below is just averaging the alpha values, which I think would be equivalent to a 50% point in the linear blend?
(a + b) / 2
In general, the alpha channel should be blended exactly like the other three channels, so maybe something like:
void mask_blend(Image& img1, const Image& img2, const Image& mask) {
int width = img1.GetWidth(), height = img1.GetHeight();
if (img2.GetWidth() != width || img2.GetHeight() != height) {
throw Error(_("Images used for blending in masked_blend function must have the same size"));
}
if (mask.GetWidth() != width || mask.GetHeight() != height) {
throw Error(_("Mask used for blending in masked_blend function must have the same size as the images"));
}
UInt size = width * height;
// these have the following structure:
// [pixel1red, pixel1green, pixel1blue, pixel2red, pixel2green, pixel2blue, pixel3red, etc...]
Byte *data1 = img1.GetData(), *data2 = img2.GetData(), *dataM = mask.GetData();
// for each subpixel...
for (UInt i = 0 ; i < (size * 3) ; ++i) {
data1[i] = (data1[i] * dataM[i] + data2[i] * (255 - dataM[i])) / 255;
}
if (img1.HasAlpha() && img2.HasAlpha()) {
// these have the following structure:
// [pixel1alpha, pixel2alpha, pixel3alpha, etc...]
Byte *alpha1 = img1.GetAlpha(), *alpha2 = img2.GetAlpha();
for (UInt i = 0 ; i < size ; ++i) {
// use mask's red channel to blend alpha (all mask channels should be identical since it's grey scale)
alpha1[i] = (alpha1[i] * dataM[i*3] + alpha2[i] * (255 - dataM[i*3])) / 255;
}
}
}
Yeah, realized that averaging was definitely wrong while I was thinking it over today. Lemme poke around with that and see what I can get together.
Github closed this automatically when I merged in the other PR. I've got a pre-release build up, was hoping you could double check that it behaves the way you expect it to - just used your snippet as is.
https://github.com/haganbmj/MagicSetEditor2/releases/tag/v2.5.0
just used your snippet as is.
That's a bold move, you like living dangerously. Did some quick tests, it seems to be behaving correctly. Will do more tests these coming days.
Thank you so much for your quick reaction time and your help, much appreciated!
just used your snippet as is.
That's a bold move, you like living dangerously. Did some quick tests, it seems to be behaving correctly. Will do more tests these coming days.
Thank you so much for your quick reaction time and your help, much appreciated!
For whatever reason this one just caught my interest, I've been pretty absent from MSE and Magic in general the last year or two otherwise.
I've been pretty absent from MSE and Magic in general the last year or two otherwise.
No worries. Anyway, did a bit more testing, everything seems fine so I'm closing this. Thanks again!
If I blend the following two images: and with this call:
linear_blend(image1: "square.png", image2: "circle.png", x1: 0.4, x2: 0.6, y1: 0, y2: 0)
I get the following result:
It uses the alpha channel of the
image1
parameter, and ignores the alpha channel of theimage2
parameter. The pixels which should be transparent on the circle are replaced with black pixels (their correct value, but ignoring the alpha).The
masked_blend
function seems to have the same problem. It uses the alpha channel of thelight
parameter, and ignores the one from thedark
parameter.