Matte around text?

Hi!

I have a problem I haven’t managed to get my head around, nor has Google provided any useful help.

What I am trying to do is to somehow define or apply a matte for translucent pixels.

So that any pixels that aren’t opaque will be get a opaque background color.

Here are two comparisons. The above image has translucent pixels (which I don’t want) and the below image has white matte:

http://gamadu.com/temp/epgmatte.png

I was thinking about going through all the pixels, doing some color calculations. Isn’t there a better way?

You could do it with 2 text render passes couldn’t you?
First pass using your matte colour, with anti-aliasing off, so every touched pixel gets full colour.
Second pass using text colour, with anti-aliasing on.

Wanting to do this just seems so wrong; though i’m sure you have a legitimate reason =)

:edit:

Oh hang on, with anti-aliasing off different pixels will be touched…
Perhaps for the matte pass you can get what you want by using one of the more exotic alpha composites?

What precisely is the use-case? If you’re drawing monochrome onto a transparent background, as in your example image, then you could do it with IndexedColorModel (possibly using two models for the same raster: draw with a model which has no transparency and then use the raster with a model which has the 0 value as fully transparent).

The use case… hm… you’ll find it strange.

I’m dynamically generating a png image, that will be displayed in a web browser of a set-top-box. This browser does not support translucent png images, only bitmask images (1 or 0 transparency). It can display translucent png images, but will convert any translucent pixels to a default matte color. I want to define my own matte color, so the image appears right on a background of the same color.

I think I’ll just add the matte color to any translucent pixels, seems like the most straightforward trick.

Just fill the background with a solid color before drawing your text, no transparency. If you placed the matte text over anything but a solid color, it would look like crap anyway.

On 2nd look, it appears to be dead simple - embarrisingly so…

  1. Make sure you image you are drawing onto only has 1 bit transparency, and starts off initialised to clear+transparent.

getGraphicsConfiguration.createCompatibleImage(width,height,Transparency.BITMASK);

worked for me.
Though i’m sure one of BufferedImage’s more complex constructors could do it too.
2) Don’t forget to turn on the text anti-alias hint.
Then, draw the text in 2 passes as I mentioned before.

  1. First pass, draw with your matte colour, any pixels touched will be turned from 0x00000000, to 0xFFrrggbb. (where rrggbb is your matte colour).
  2. Second pass, draw with your text colour, the pixels touched will already contain 0xFFrrggbb and so will be replaced with the desired matte/colour blend - according to the alpha values generated by the anti-aliasing text rasterizer.

No need to mess around with AlphaComposites at all!

:edit:

Nvm, doesn’t work due to the rounding :slight_smile:
When drawing the matte, pixels are only touched with an alpha >127.
I’m sure it’s possible & simple to fix though…

That I cannot do. If I could, I wouldn’t need to ask about it.

In any case, the text gets placed on top of a video stream, and a translucent solid color. So, it does matter!

I think it should be doable by writing your own ColorModel…

Or how about BandCombineOp on an alpha-premultiplied image, assuming that it clips the results to range? Haven’t tested it, but it might work. r’ = r + r0(255 - alpha) where r0 is from the matte colour, alpha’ = 255 alpha. Doesn’t work. It doesn’t clip the results to range.