I posted a question about drawing text onto a pixmap to generate dynamic textures at runtime, and that problem was resolved here
Is there an easy way that I can tint the font that I copy to a new pixmap, or do I need to do it manually pixel by pixel? I can't find anything obvious in the libgdx library or on Google.
My current process is:
create a new pixmap
draw a character onto that pixmap
convert the pixmap into a texture for rendering.
At some point in that process I'm like to be able to tint the font at runtime.
Code updated to test Jyro117's answer. (Not working, see image below)
// Set up the base image
Pixmap newPixmap = new Pixmap(backImage.getWidth(),
backImage.getHeight(), Format.RGBA8888);
newPixmap.drawPixmap(backImage, 0, 0);
// Copy out the letter from our fontsheet
// and draw the char to a new pixmap
Glyph glyph = fontData.getGlyph(getLetterToDraw().charAt(0));
Pixmap charPixmap = new Pixmap(glyph.width, glyph.height,
Format.RGBA8888);
charPixmap.drawPixmap(fontPixmap, 0, 0, glyph.srcX, glyph.srcY,
glyph.width, glyph.height);
// try to tint it?!
charPixmap.setColor(1, 0, 0, 100);
charPixmap.fillRectangle(0, 0, newPixmap.getWidth(),
newPixmap.getHeight());
// copy the character to our new bitmap
newPixmap.drawPixmap(charPixmap, (BLOCK_SIZE - glyph.width) / 2,
(BLOCK_SIZE - glyph.height) / 2);
texture = new Texture(newPixmap);
newPixmap.dispose();
charPixmap.dispose();
Pixmap has all the functions you need to tint it.
Get a pixmap of the font (in your case fontPixmap)
Make sure alpha blending is enabled.
Set the color, (setting alpha to the desired level)
Draw rectangle over entire font image (0,0,width,height)
Now the pixmap of your font has the desired tinting
Hopefully that clears it up for you.
Edit:
Alright, so I see what exactly you mean, it would appear there is no way by default to change the 'type' of blending for Pixmap. At least without me looking into the native code under the covers. BitmapFont gets around this by using vertex data for the glyph and renders each one as a shape instead of image. So in order to do this you will have to do it with two passes:
First we fill the pixmap with the desired color and alpha (note: the values for this are between 0f and 1f, so your alpha should be something like 0.3f not 100)
Next you iterate over all pixels of the image and are looking for pixels which have their alpha value below a certain threshold (should be around 0.3f). Then you could either set the alpha of those pixels below the threshold to 0, or maybe do something fancier like Math.pow(alpha, 3), etc. Basically the alpha you just added to the image (using source over blending) you want to reduce/remove, but only for pixels which are supposed to be transparent. You may have to play around with different values or reduction techniques to get it looking correctly.
Note: You can iterate over the pixel data by calling getPixel() or get the Bytebuffer with getPixels() and the 4th byte will be the pixel's alpha value between 0 and 255.
Edit 2:
I just thought of an alternative way to do this is to use a Frame Buffer.
Render your font texture onto the frame buffer.
Draw a colored rectangle with alpha over the entire frame buffer using the proper alpha blending function (Not sure which one off the top of my head but you want one which only applies if dst has an alpha greater than 0).
Grab the texture from the frame buffer and use that as your tinted font.
Related
For a Java program ("regular" program, not Applet and/or Android etc.), I have PNGs with transparency which are to be loaded and drawn atop other pictures, which is working perfectly fine. Now, for the case that there is no other picture below them (the determination of whether that is the case is not an issue, the respective code is already workingly implemented), I want them made opaque, but not in the sense of simply setting a background color; since the png source files concerned are fully colored, just with reduced opacity (alpha value) on them, it would, I guess, be no problem to simply increase the opacity of all the colors to 100%, I just don't know the commands to do it. Preferred and so far targeted way of doing it is by having them drawn in a BufferedImage, then modified respectively, but as said: How?
TLDR: images from .png with <100% opacity (same value on whole pic), how to make opaque in Java, preferrably with BufferedImage or even simpler
thanks in advance for any answers
You can try RescaleOp to scale the alpha component all the way to opaque:
float[] scales = { 1f, 1f, 1f, 0f }; // R, G, B, A
float[] offsets = {0f, 0f, 0f, 255f}; // R, G, B, A
RescaleOp rescaler = new RescaleOp(scales, offsets, null);
BufferedImage opaque = rescaler.filter(original, null);
See this Java 2D tutorial for more info.
I'm trying to change the transparency of an image over time, and I'm doing this with the method drawImage() from java.awt.Graphics. I know there's a lot of different answers online about how to do this, but I can't find a one that is simple enough for me to understand and implement.
Let's just say I have a BufferedImage image, and I want to draw this image with a 50% opacity. How would I initialize image and what would I do to adjust the alpha level of the image when I draw it. It would be great if I could use the method drawImage() and do something with that to change the transparency of the image, but it's probably not that simple.
Never tried it, but I think the basic code would be:
AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha);
g2d.setComposite(ac);
g2d.drawImage(...);
Using image filter.
float[] scales = { 1f, 1f, 1f, 0.1f };
float[] offsets = new float[4];
RescaleOp rop = new RescaleOp(scales, offsets, null);
g2d.drawImage(buffimg, rop, 0, 0);
4th element in scales array is transparency, this value goes between 0 - 1
Answer by camickr will make the entire component apply the alpha including all inner components. But that will be much faster.
Warning: Use Image Filters with Care
ref: http://www.informit.com/articles/article.aspx?p=1013851&seqNum=2
I have a BufferedImage with alpha transparency, which I need to save as GIF with index transparency. There are no semi-opague pixels, therefore a conversion should be possible.
Using the code found under http://gman.eichberger.de/2007/07/transparent-gifs-in-java.html, I define a transparency color (green, for instance, which is not part of the current image) and make it transparent. Works fine, BUT it mixes up the color table and all the colors look awful (although I only use 3 different colors).
Is there a way to adjust this or else another way of converting such an ARGB-Image to an indexed one without significant quality loss?
The way my image gets constructed:
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = (Graphics2D)image.getGraphics();
graphics.setColor(backgroundColor);
graphics.fillRect(0, 0, width, height);
// Some more painting here
graphics.dispose();
Thanks for any help!
Using ImageIO to handle transparency especially when saving as a GIF image is a nightmare. Transparency support in ImageIO is incomplete for different image formats and even same image format but different variations.
If you already has a binary transparent BufferedImage, I've got a color quantization tool and a GIF encoder to save it as GIF with transparency. If the actual colors of the image are less than 256, no quantization will be applied. Otherwise, colors will be reduced to less than 256 but the transparent color is retained. Dithering can be applied during quantization process, so the resulting image size might be larger than usual.
The following screenshot shows two images: the one to the left is the original PNG image with alpha channel transparency while the right hand side one is a transparent GIF image converted from the same PNG image. The GIF image is actually reduced to 128 colors but the quality is great. (PNG: 49K, GIF: 17K)
Image source: http://svg2rlg.googlecode.com/svn-history/r2/trunk/test-suite/png/butterfly.png
I have a bitmap file, that serves as a mask for a view. It has multiple rectangular areas with different colors on a white background. When the user touches the View, I use the X and Y coords of this event to look up the color of the mask (which is not displayed) and do things based on the color code returned.
The problem is: loading this mask with BitmapFactory results in a Bitmap object that is scaled. This way the colors get distorted a bit. If I have e.g. a solid rectangle with color (155, 155, 0), then it'll be like (148, 158, 0), (150, 154, 0), and so on. But I need to get the exact color.
So how do I load the raw bitmap, without any scaling / compressing / stuff like that?
I'm trying to blend 2 images together in the following way:
Image 1 should be drawn as the base image. Image 2 should be drawn overtop of image 1. Anywhere image 2 is non-transparent, it should replace the contents of image 1 (not blend, but overwrite what is there). Wherever image 2 is transparent, image 1 should show through. I've tried to do this with the following code, but I'm obviously doing something incorrectly with the blending.
gl.glEnable(GL.GL_BLEND);
if (iconTexture1 != null)
{
gl.glEnable(GL.GL_TEXTURE_2D);
iconTexture1.bind();
double red = (double) fillColor.getRed() / 255.0;
double green = (double) fillColor.getGreen() / 255.0;
double blue = (double) fillColor.getBlue() / 255.0;
gl.glColor4d(red, green, blue, this.getOpacity());
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
TextureCoords texCoords = iconTexture1.getImageTexCoords();
gl.glScaled(width, height, 1d);
dc.drawUnitQuad(texCoords);
}
if (iconTexture2 != null)
{
gl.glEnable(GL.GL_TEXTURE_2D);
iconTexture2.bind();
// image2 is all white, so color it here
gl.glColor4d(1d, 0d, 0d, 1d);
// TODO: What blend function should I be using here to allow image 2 to overwrite what is already there?
TextureCoords texCoords = iconTexture2.getImageTexCoords();
gl.glScaled(width, height, 1d);
dc.drawUnitQuad(texCoords);
}
Any help to make this work correctly would be appreciated. Thanks.
Jeff
There are a few things that might be issues:
You shouldn't turn the blending function on until after you have drawn image 1. Doing so before will blend image 1 with whatever was there already.
I'm not a big texture user, but I think using texture will override the color of the quad, including any alpha you have specified; so unless the texture has alpha you won't get any blending.
If you have z-buffering enabled, then maybe image 2 is behind image1; that would obscure it, even if image 2 is transparent. Special methods have to be used to draw transparent 3d.
A good way of working with OpenGL things that don't seem to work is to remove all the complexity, and then add it back bit by bit. The texture is your most complex part - leave that 'til last.