SFML community forums
Help => Graphics => Topic started by: Metapyziks on December 27, 2009, 10:57:07 pm
-
I can't draw onto a texture with Image.Copy() with applyAlpha = true if the area being copied onto has 0 alpha (the alpha is inherited for some reason). Any way to counter this without doing it pixel by pixel?
-
Sorry I don't get it. If applyAlpha is true, it's normal that pixels having 0 alpha don't get copied, they are fully transparent.
-
Sorry I don't get it. If applyAlpha is true, it's normal that pixels having 0 alpha don't get copied, they are fully transparent.
I mean if the target area has an alpha of 0, a pixel with alpha 255 won't be drawn onto it.
-
Ah I see, sorry.
It's because the alpha value is left unchanged. It's probably wrong, I should rather use the following formula:
a = src.a + dst.a * (1 - src.a)
I'll fix this as soon as I can, thanks for your feedback :)
EDIT: fixed in SFML 2
-
Thanks :)
Is there a way for me to get this fix?
-
Which version of SFML do you use?
-
Which version of SFML do you use?
1.5
I've cheaply fixed it by having the transparent areas made red (none of the images drawn onto it have red in them) and then copy over the red value to be their alpha values, pixel by pixel.
-
If you want you can fix it yourself and recompile SFML, but then you'll have to distribute your modified version of SFML.
-
Just checking if this is right:
////////////////////////////////////////////////////////////
/// Copy pixels from another image onto this one.
/// This function does a slow pixel copy and should only
/// be used at initialization time
////////////////////////////////////////////////////////////
void Image::Copy(const Image& Source, unsigned int DestX, unsigned int DestY, const IntRect& SourceRect, bool ApplyAlpha)
{
// Make sure both images are valid
if ((Source.myWidth == 0) || (Source.myHeight == 0) || (myWidth == 0) || (myHeight == 0))
return;
// Make sure both images have up-to-date arrays
EnsureArrayUpdate();
Source.EnsureArrayUpdate();
// Adjust the source rectangle
IntRect SrcRect = SourceRect;
if (SrcRect.GetWidth() == 0 || (SrcRect.GetHeight() == 0))
{
SrcRect.Left = 0;
SrcRect.Top = 0;
SrcRect.Right = Source.myWidth;
SrcRect.Bottom = Source.myHeight;
}
else
{
if (SrcRect.Left < 0) SrcRect.Left = 0;
if (SrcRect.Top < 0) SrcRect.Top = 0;
if (SrcRect.Right > static_cast<int>(Source.myWidth)) SrcRect.Right = Source.myWidth;
if (SrcRect.Bottom > static_cast<int>(Source.myHeight)) SrcRect.Bottom = Source.myHeight;
}
// Then find the valid bounds of the destination rectangle
int Width = SrcRect.GetWidth();
int Height = SrcRect.GetHeight();
if (DestX + Width > myWidth) Width = myWidth - DestX;
if (DestY + Height > myHeight) Height = myHeight - DestY;
// Make sure the destination area is valid
if ((Width <= 0) || (Height <= 0))
return;
// Precompute as much as possible
int Pitch = Width * 4;
int Rows = Height;
int SrcStride = Source.myWidth * 4;
int DstStride = myWidth * 4;
const Uint8* SrcPixels = Source.GetPixelsPtr() + (SrcRect.Left + SrcRect.Top * Source.myWidth) * 4;
Uint8* DstPixels = reinterpret_cast<Uint8*>(&myPixels[0]) + (DestX + DestY * myWidth) * 4;
// Copy the pixels
if (ApplyAlpha)
{
// Interpolation using alpha values, pixel by pixel (slower)
for (int i = 0; i < Rows; ++i)
{
for (int j = 0; j < Width; ++j)
{
// Get a direct pointer to the components of the current pixel
const Uint8* Src = SrcPixels + j * 4;
Uint8* Dst = DstPixels + j * 4;
// Interpolate RGB components using the alpha value of the source pixel
Uint8 Alpha = Src[3];
Dst[0] = (Src[0] * Alpha + Dst[0] * (255 - Alpha)) / 255;
Dst[1] = (Src[1] * Alpha + Dst[1] * (255 - Alpha)) / 255;
Dst[2] = (Src[2] * Alpha + Dst[2] * (255 - Alpha)) / 255;
// Get the new alpha value for the destination pixel
Dst[3] = (Alpha * Alpha + Dst[3] * (255 - Dst[3])) / 255;
}
SrcPixels += SrcStride;
DstPixels += DstStride;
}
}
else
{
// Optimized copy ignoring alpha values, row by row (faster)
for (int i = 0; i < Rows; ++i)
{
memcpy(DstPixels, SrcPixels, Pitch);
SrcPixels += SrcStride;
DstPixels += DstStride;
}
}
// The texture will need an update
myNeedTextureUpdate = true;
}
-
This one should be more correct ;)
Dst[3] = Alpha + (Dst[3] * (255 - Alpha)) / 255;
-
This one should be more correct ;)
Dst[3] = Alpha + (Dst[3] * (255 - Alpha)) / 255;
Ok, thanks :)
Edit: I can confirm this works perfectly. Do you want the updated Image.cpp?
My computer studies teacher asked that I fix at least one bug or add a feature to any open source project during the holidays, and I was wondering if it would be ok to use this.