Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: CreateMaskFromColor leaves a border (with possible solution)  (Read 7714 times)

0 Members and 1 Guest are viewing this topic.

nitram_cero

  • Full Member
  • ***
  • Posts: 166
    • View Profile
The issue:



When I apply a mask by color key (Image::CreateMaskFromColor()), I get borders.

The solution:
After creating the mask, for each transparent pixel (i.e. Alpha=0):
Modulate the color for each non-transparent neighbour (only 4 actually, not the corners) and use this color for the pixel.

So, if you have:

Code: [Select]
TTT
TXR
TBT


(T=transparent, X=the transparent pixel you're processing, R=red, B=blue)

Then
X=R*B but keeping alpha at 0.

This way, the intrinsic "border", that is rendered because of OpenGL's filtering (when Image::IsSmooth()), now renders the appropiate color.

This could be implemented WAY faster and on the same pass as the mask creation, but as that's not gonna happen anytime soon... I'll leave the code to "fix" the images here.

Code: [Select]
inline void fixPixel(const Image &src, Image &dst, unsigned int x, unsigned int y)
{
if(src.GetPixel(x, y).a == 0) {
bool apply=false;
Color newCol(255,255,255, 0); //modulate white, keep alpha=0
Color nearCol;

nearCol=src.GetPixel(x, y-1);
if(nearCol.a) { newCol*=nearCol; apply=true; }

nearCol=src.GetPixel(x-1, y);
if(nearCol.a) { newCol*=nearCol; apply=true; }

nearCol=src.GetPixel(x+1, y);
if(nearCol.a) { newCol*=nearCol; apply=true; }

nearCol=src.GetPixel(x, y+1);
if(nearCol.a) { newCol*=nearCol; apply=true; }

if(apply)
dst.SetPixel(x, y, newCol);

}
}

Image fixColorKeyImage(Image &im)
{
Image newIm(im);
for(unsigned int y=1; y<im.GetHeight()-1; y++) {
for(unsigned int x=1; x<im.GetWidth()-1; x++) {
fixPixel(im, newIm, x, y);
}
}
return newIm;
}


Then callit as this:
Code: [Select]

Image im;

im.LoadFromFile("image.bmp");
im.CreateMaskFromColor(Color(255, 128, 64));
im=fixColorKeyImage(im);



I hope it helps, at least as a start...

-Martín

jordanday

  • Newbie
  • *
  • Posts: 1
    • View Profile
    • http://www.roboninja.com
CreateMaskFromColor leaves a border (with possible solution)
« Reply #1 on: May 05, 2009, 10:00:31 pm »
This may just be an artifact from the image you posted here, but are you sure you're saving your original image without any sort of compression/anti-aliasing-type of operations in your image editor? The border that is appearing could be a result of blending between the mask color and the actual image when you save the original image. The border is actually a different color than the original mask color, which is why it isn't being removed.

You might try turning off any sort of blending/anti-aliasing features in your image editor. This could also be an artifact from JPEG compression... I don't really know enough to say for sure, just a suggestion of something you might want to check in to.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
CreateMaskFromColor leaves a border (with possible solution)
« Reply #2 on: May 05, 2009, 11:12:13 pm »
If you don't want filtering then just turn it off. If you want filtering without border artifacts then put an appropriate alpha channel in your image.

What you currently get is just the expected behaviour.
Laurent Gomila - SFML developer

nitram_cero

  • Full Member
  • ***
  • Posts: 166
    • View Profile
CreateMaskFromColor leaves a border (with possible solution)
« Reply #3 on: May 05, 2009, 11:32:03 pm »
Quote from: "jordanday"
This may just be an artifact from the image you posted here, but are you sure you're saving your original image without any sort of compression/anti-aliasing-type of operations in your image editor? The border that is appearing could be a result of blending between the mask color and the actual image when you save the original image. The border is actually a different color than the original mask color, which is why it isn't being removed.

You might try turning off any sort of blending/anti-aliasing features in your image editor. This could also be an artifact from JPEG compression... I don't really know enough to say for sure, just a suggestion of something you might want to check in to.


It's a BMP, no artifacts. With PNGs, it's the same. The image editor is MSPaint, so you can't get rawer than that.

The bilinear filtering (anti-aliasing) is applied by OpenGL, and it's unavoidable... as it passes it blends

Quote
The border that is appearing could be a result of blending between the mask color and the actual image when you save the original image.

You're right on this one, but not because of the application, but because of the graphics card's way of doing the filtering (including Alpha in the anti-aliasing instead of using just RGB)





Laurent, with all due respect, the "expected behaviour" sucks.

If you use a color key is because you want to completly remove the color you're asking to remove.

It's the expected behaviour of a Graphics card, not a 2D games library.

I do want filtering (for zooming), but I do not want an outline border.

I mean... in which real-life situation you would like a colorkey'd with that artifacts?
I know that the pixels get modified, but if you're really concerned in keeping those pixels as loaded, then you probably aren't color-keying anyway.

Thanks
-Martín

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
CreateMaskFromColor leaves a border (with possible solution)
« Reply #4 on: May 06, 2009, 08:54:46 am »
I think you're using the wrong method. If you want a perfect alpha channel then just setup your image properly before loading it. Creating the mask at runtime is a helper tool if you want fast results, but it's not the right way of doing things at the end.
It's like wanting a super high resolution 7.1 music from a 8000Hz mono wav file.

Moreover, like you just showed, this smart filter can be applied on top of what SFML provides.
Laurent Gomila - SFML developer

dwarfman78

  • Full Member
  • ***
  • Posts: 228
  • I'm bietzsche, Nietzsche !
    • MSN Messenger - cd4c@hotmail.com
    • View Profile
    • Email
CreateMaskFromColor leaves a border (with possible solution)
« Reply #5 on: May 06, 2009, 01:23:42 pm »
Quote
If you want a perfect alpha channel then just setup your image properly before loading it. Creating the mask at runtime is a helper tool if you want fast results, but it's not the right way of doing things at the end.


Can you explain what is the right way ?
@dwarfman78
github.com/dwarfman78

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
CreateMaskFromColor leaves a border (with possible solution)
« Reply #6 on: May 06, 2009, 01:38:02 pm »
The right way is to create the alpha channel yourself with an image editor. So that your image already looks like exactly what you expect before being loaded by SFML, and you get no surprise.
Laurent Gomila - SFML developer

dwarfman78

  • Full Member
  • ***
  • Posts: 228
  • I'm bietzsche, Nietzsche !
    • MSN Messenger - cd4c@hotmail.com
    • View Profile
    • Email
CreateMaskFromColor leaves a border (with possible solution)
« Reply #7 on: May 06, 2009, 01:43:24 pm »
Is it possible with the bmp format ?

Quote
An alpha channel (for transparency) may be stored in a separate file


http://en.wikipedia.org/wiki/Windows_bitmap
@dwarfman78
github.com/dwarfman78

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
CreateMaskFromColor leaves a border (with possible solution)
« Reply #8 on: May 06, 2009, 01:53:59 pm »
No, you have to use a format that can hold an alpha channel: TGA or PNG.

If you don't want to bother with an image editor, just use the functions you've written and save the resulting image with SFML ;)
Laurent Gomila - SFML developer

dwarfman78

  • Full Member
  • ***
  • Posts: 228
  • I'm bietzsche, Nietzsche !
    • MSN Messenger - cd4c@hotmail.com
    • View Profile
    • Email
CreateMaskFromColor leaves a border (with possible solution)
« Reply #9 on: May 06, 2009, 02:00:37 pm »
Ok thank you, i'm not the original poster though.
@dwarfman78
github.com/dwarfman78

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
CreateMaskFromColor leaves a border (with possible solution)
« Reply #10 on: May 06, 2009, 02:03:11 pm »
Quote
i'm not the original poster though

Oops :oops:
Laurent Gomila - SFML developer

nitram_cero

  • Full Member
  • ***
  • Posts: 166
    • View Profile
CreateMaskFromColor leaves a border (with possible solution)
« Reply #11 on: May 07, 2009, 06:08:39 pm »
Keeping it minimal :P

I just made the topic, not as a feature request, but as a reference for anyone that asks about those borders. :)



But anyway, if you have an alpha mask made by a graphics software, this error could still exist, as the graphics card does linear filtering on every component (RGBA)

Probably most graphics software do what I do in my function to leave a border of the same color and avoid these kind of problems, before saving.

But supposing that it leaves an orange "RGB" where Alpha=0... it would be the same deal.

The only thing this filter does is fixing for Alpha=0... so no viewable color data is ever lost.


Quote
Is it possible with the bmp format ?

You'd have to keep two bmps, one with the image and another one with the alpha mask (optimally grayscale).
But that's just an arcaic way.  The best solution is as Laurent said, using TGA or PNG.

Nevertheless, this solution is good for big images that could be better compressed with the JPEG format, and keeping the mask separately in a grayscale RLE encoded bitmap or another non destructive compressed format...
or even a JPEG if you don't really care about artifacts in your transparency.

Best regards
-Martín

 

anything