Page 1 of 1

PixelEffect: color to alpha

Posted: Sat Jul 21, 2012 10:17 pm
by NTGuardian
I'm new to LOVE and am doing my best to learn it. Finished all the tutorials in the Wiki, save for the videos. Right now, I'm trying to figure out how to use PixelEffects. So here's the problem:

I'm trying to use Civ3 animations, and those animations are on a pink field. I'm trying to use pixel effects to remove the pink and make it transparent. Getting rid of the pink itself isn't too difficult; what is difficult is removing the residual pixels that have a pinkish hue, removing the pink and increasing the alpha component (this would allow shadows to appear, for example).

Here's a snippet of the most recent attempt at the code:

Code: Select all

effect = love.graphics.newPixelEffect [[
		vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords)
		{
			vec4 rColor = Texel(texture, vec2(1, 1));
			vec4 AlphaColor = Texel(texture, texture_coords);
			vec4 fColor;

			if (all(equal(AlphaColor, rColor)))
			{
				AlphaColor.r -= rColor.r;
				AlphaColor.g -= rColor.g;
				AlphaColor.b -= rColor.b;
				AlphaColor.a = abs(AlphaColor.r)+abs(AlphaColor.g)+abs(AlphaColor.b);
				AlphaColor.a /= 3;

				fColor = Texel(texture, texture_coords);
				fColor.a = AlphaColor.a;
			}
			else
			{
				fColor = Texel(texture, texture_coords);
				return fColor;
			}
		}
	]]
Here's the image I'm trying to use, and the result in LOVE:

Re: PixelEffect: color to alpha

Posted: Sat Jul 21, 2012 11:49 pm
by Robin
Welcome!

Apart from the problems with those animations, you know, legal-wise, is there a reason you're not using an image editor like the GIMP to get rid of that pink?

Anyway, there's probably a formula for checking how "close" two colours are, so you could use that to translate the RGBA to something appropriate, but I don't know such an formula, unfortunately.

Re: PixelEffect: color to alpha

Posted: Sun Jul 22, 2012 12:04 am
by josefnpat
I think the biggest problem here is that the "pink" (#F601ED) (see A) is not actually pink that is usually used for these types of transformations (#FF00FF).

Looking closely, you see that the tank itself has an alpha layer that has been flattened (see B) onto this "almost pink" background.

And to be even further to the point, there is also a shadow (see C) (implying that there should be an alpha layer)
nZTFD.png
nZTFD.png (9.81 KiB) Viewed 456 times
What you're going to find that, unless you remove anything remotely close to #FF00FF (e.g. #[DD->FF][00->33][DD->FF]), you're not going to have an algorithm that will properly "unflatten" this image. And even if do use such a filter, it's not going to look very good anyways.

My suggestion here is to either clean up the tanks in GIMP/Photoshop and use PNG's, or to find better sprites to use.

Re: PixelEffect: color to alpha

Posted: Sun Jul 22, 2012 1:29 am
by NTGuardian
Thanks for the replies.

I could use GIMP, but seeing as animations may have hundreds of frames just for one action, I'd prefer to develop an algorithm that is able to clear the colors from the image rather than clear every single image (and I believe that if I use the user-generated files, there should be no legal issue, since technically they don't belong to Civ; this is one of those animations). Also, since these files are used by Civ with pink and appear in the game just fine, I know it's possible; just want to know HOW.

I've tried a variety of ways to eliminate the "near" colors. This was my latest attempt:

Code: Select all

effect = love.graphics.newPixelEffect [[
      vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords)
      {
         vec4 lColor = Texel(texture, vec4(50 / 256, 0, 45 / 256, 1));
         vec4 hColor = Texel(texture, vec4(246 / 256, 19 / 256, 237 / 256, 1));
         vec4 AlphaColor = Texel(texture, texture_coords);
         vec4 fColor;

         if (all(greaterThanEqual(AlphaColor, lColor)) && all(lessThanEqual(AlphaColor, hColor)))
         {
            AlphaColor.r -= rColor.r;
            AlphaColor.g -= rColor.g;
            AlphaColor.b -= rColor.b;
            AlphaColor.a = abs(AlphaColor.r)+abs(AlphaColor.g)+abs(AlphaColor.b);
            AlphaColor.a /= 3;

            fColor = Texel(texture, texture_coords);
            fColor.a = AlphaColor.a;
         }
         else
         {
            fColor = Texel(texture, texture_coords);
            return fColor;
         }
      }
   ]]
The idea behind this solution being to capture the range between the lower values and the higher values and subject them to the color-to-alpha treatment (which WOULD preserve the shadows and such; when it runs over the entire image, it's as if it were done by GIMP, but of course I only want the purpleish areas, not the whole image). However, the result was never true, and the tank image was simply drawn unmodified, pink and all. The problem seems to stem from the use of 237/256 et al: for whatever reason, it won't make a value. I've tried float(237/256), but that hasn't worked either.

Re: PixelEffect: color to alpha

Posted: Sun Jul 22, 2012 2:31 am
by josefnpat
NTGuardian wrote:Thanks for the replies.

I could use GIMP, but seeing as animations may have hundreds of frames just for one action, I'd prefer to develop an algorithm that is able to clear the colors from the image rather than clear every single image (and I believe that if I use the user-generated files, there should be no legal issue, since technically they don't belong to Civ; this is one of those animations). Also, since these files are used by Civ with pink and appear in the game just fine, I know it's possible; just want to know HOW.

I've tried a variety of ways to eliminate the "near" colors. This was my latest attempt:

Code: Select all

effect = love.graphics.newPixelEffect [[
      vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords)
      {
         vec4 lColor = Texel(texture, vec4(50 / 256, 0, 45 / 256, 1));
         vec4 hColor = Texel(texture, vec4(246 / 256, 19 / 256, 237 / 256, 1));
         vec4 AlphaColor = Texel(texture, texture_coords);
         vec4 fColor;

         if (all(greaterThanEqual(AlphaColor, lColor)) && all(lessThanEqual(AlphaColor, hColor)))
         {
            AlphaColor.r -= rColor.r;
            AlphaColor.g -= rColor.g;
            AlphaColor.b -= rColor.b;
            AlphaColor.a = abs(AlphaColor.r)+abs(AlphaColor.g)+abs(AlphaColor.b);
            AlphaColor.a /= 3;

            fColor = Texel(texture, texture_coords);
            fColor.a = AlphaColor.a;
         }
         else
         {
            fColor = Texel(texture, texture_coords);
            return fColor;
         }
      }
   ]]
The idea behind this solution being to capture the range between the lower values and the higher values and subject them to the color-to-alpha treatment (which WOULD preserve the shadows and such; when it runs over the entire image, it's as if it were done by GIMP, but of course I only want the purpleish areas, not the whole image). However, the result was never true, and the tank image was simply drawn unmodified, pink and all. The problem seems to stem from the use of 237/256 et al: for whatever reason, it won't make a value. I've tried float(237/256), but that hasn't worked either.
I do something to this effect in a github project of mine, where I try and find unique tiles. Some tiles are so similar, they can be considered a duplicate of a different tile.

Take a look at how I do it with the significant_bits variable: https://github.com/josefnpat/Sprite-She ... in.lua#L41