I have two RenderedImages. I want to do an Overlay Operation with these two images and therefore they need to match in data type and the number of bands.
The problem I have is that one image has 3 bands (RGB) and the second image has 4 bands (ARGB).
My question is how can I add an Alpha Channel to the first image so I can do the Overlay Operation?
EDIT
Ok, I found a method of adding an Alpha Channel to the first image. Below is the code. I simply created a single banded constant image and merged it with my first image.
ParameterBlock pb = new ParameterBlock();
pb.add(new Float(finalImage.getWidth())).add(new Float(finalImage.getHeight()));
pb.add(new Byte[] {new Byte((byte)0xFF)});
RenderedImage alpha = JAI.create("constant", pb);
finalImage = BandMergeDescriptor.create(finalImage, alpha, null);
The problem I have now is that everytime I add an overlay the image changes colors. All the colors become nuances of red or pink. When I add a second overlay, the image becomes normal again, but the first overlay changes colors. All black areas become white.
Also the background of the overlay is not transparent. It is grey.
Below are examples of the images, so you see how the change colors:
As you can see, the picture and overlays change colors and the background of the overlay isn't transparent.
Can you help me solve this problem, so that the image is always displayed correctly? Thanks!
You can try to create a new BufferedImage with ARGB-model, and just paint the non-transparent background picture into this new BufferedImage. Then you have a BufferedImage with alpha-channel (although all of the pixels are opaque), so the Composition should hopefully work.
im not sure about TYPE_4BYTE_ARGB as I usually work with BufferedImages of TYPE_INT_ARGB but I have often used the method of drawing a RGB BufferedImage to a new ARGB BufferedImage and then drawing that onto other things without problem. the change in color would suggest an unwanted change is being made to the other channels in the overlay process as it doesn't seem to be specific to a specific image. If your overlay operation is similar to drawing one image onto another with alpha I would probably suggest using the Graphics.drawImage()/drawRenderedImage() method for the overlay itself not to mention the background should not even need alpha in this case.
the code:
public RenderedImage overlay(RenderedImage back, RenderedImage front, AffineTransform overlayTransformation)
{
BufferedImage newBack = new BufferedImage(back.getWidth(), back.getHeight(), TYPE_3BYTE_RGB);
newBack.setData(back.getData());
Graphics2D graphics = (Graphics2D)(newBack.getGraphics());
graphics.drawRenderedImage(front, overlayTransformation);
return newBack;
}
you may want to ensure the original back Raster is not modified though.
Related
I have a quadrilateral drawn in Path2D, and I would like for there to be an image on it. More specifically, I am trying to draw an image of my choice to 4 different points on a quadrilateral. In my case, it is a parallelogram. I do not want the image to go over the paralellogram. A better way to see what I am trying to say is to see the screenshot below.
I would like the image to be transformed to fit the green area. Not clipped.
I want the image to be pinned over the green paralellogram. However. I do not want the image to go over into the blue paralellogram, or the white space foe that matter.
So far I have tried
Researching for a way to place images directly onto Path2D.Double() objects. No answer
Rotating the image to fit the paralellogram. Didnt work.
Using AffineTransform in java. Dont get it ;-;
Thanks. I am new to java so do try to be lenient?
One way is to:
create a separate BufferedImage.
Apply a transform to the new image.
Draw your image to that new image.
Use the Shape object for the green area as a clip on the main drawing area
Draw the transformed image onto the main drawing area.
It's been a while since I have done transformations. You may have to set the transformation first and then draw the image after. Transformation has to come first.
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.transform(AffineTransform.getShearInstance(1.0, 0));
g2.drawImage(image, 0, 0, this);
}
Here is a simple example of how transforms work. You will have to spend some time on figuring out what values you need to make it work or if you might need to manually create a transformation matrix yourself.
I'm making a simple side scroller game in Java but am having trouble making the camera move with the person. My plan was to create a buffered image that could adjust the region of the image that is displaying and simply have it follow my character. However, I couldn't find any functions in the API to change the region of the buffered image that's displayed, so how could I do this? Thanks for any help provided.
//The level is created in an 800x400 pixel size, is there any way I can change
//the region myImage displays?
myImage = new BufferedImage(400, 400, BufferedImage.TYPE_INT_RGB);
Well while you will be drawing your image you have a lot of options for example this function can draw any rectangle from your original image on any rectangle of the surface you get Graphics object from.
I want to inset a image into a background and save it, both are png files with transparency, below code work fine but new image become black & white only.
BufferedImage BUFFEREDIMAGE1=ImageIO.read(new File(strPATH+"/IMAGE.png"));
BufferedImage BUFFEREDIMAGE2=ImageIO.read(new File(strPATH+"/WATERMARK.png"));
Graphics2D GRAPHICS1=BUFFEREDIMAGE1.createGraphics();
GRAPHICS1.drawImage(BUFFEREDIMAGE2,intLeft,intTop,intWidth,intHeight,null);
GRAPHICS1.dispose();
ImageIO.write(BUFFEREDIMAGE2,"png",new File(strPATH,"SAVED.png"));
The most likely cause is that at some point the colour space of the image is becoming changed. You may be better off explicitly creating a new destination BufferedImage with the RGB or RGBA format and writing both source Images into it. This removes any possible variation in that area.
I am drawing multiple resources onto a bitmap via a canvas. I would like the end result of the composite image to have a certain alpha. Right now I'm setting paint's alpha to the level i want and then drawing each bitmap with that alpha, but i know this would create a composite image of a lot of different alphas. Is there a way to apply an alpha to the entire composite image in performance friendly manner?
You could draw all the drawables fully opaque (alpha = 255) to begin with, then draw over the entire destination Bitmap using Porter-Duff MULTIPLY mode with the right source alpha to change it all at one shot.
I am developing a small program which cuts images by the color.
That's will be easiest to explain using this example image:
And I want to create a new image just with the purple form, without the black frame.
Does anyone have any ideas? I am using Java 2D so I think that I need to create an Object "Shape" with the purple area of the first image.
If the image is literally like the one you show, you could:
load the image into a BufferedImage (with ImageIO.read())
create a new BufferedImage of the same size, ensuring it has an alpha layer (e.g. set its type to BufferedImage.TYPE_4BYTE_ABGR)
"manually" go through each pixel in turn in the loaded BufferedImage, getting the pixel colour with getRGB() and checking if it's black
if the colour is black, set the corresponding pixel to transparent in the new image, else to the original colour from the first image (see setRGB() method)
save the new image (with ImageIO.write())
There are fancier ways, but this simple method is nice and understandable and will work fine for images of the type you showed.
You need to use some flood-fill algorithm that finds the boundries of the purple area:
Wikipedia has a page on it with excellent pseudo code and animations.
http://en.wikipedia.org/wiki/Flood_fill