How to create a transparent shape in the image - java

I have an image now I want to create a transparent shape in the image so that I can put another image in that shape.
I want to achieve something like this
Is there any way to do this programmatically in java or python. If not How can I do this manually.
I have linux environment and some image editor But I am not able to do this even manually.

So, the following makes use of:
The 2D Graphics API in particular, Compositing Graphics
The ImageIO API
So, starting with this...
I want to add this behind it (but peeking through)
The first thing we need to do is make a "alpha" based mask of the area we want to become transparent. For this, I'm using a RadialGradientPaint, as it allows me to produce a "fading" effect around the edges.
Now, I've already done all the math (used a simple image editor to work it out), so I know where I want the "hole" appear
BufferedImage city = ImageIO.read(new File("/Users/swhitehead/Downloads/City.jpg"));
BufferedImage mask = new BufferedImage(city.getWidth(), city.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = mask.createGraphics();
Color transparent = new Color(255, 0, 0, 0);
Color fill = Color.RED;
RadialGradientPaint rgp = new RadialGradientPaint(
new Point2D.Double(955, 185),
185,
new float[]{0f, 0.75f, 1f},
new Color[]{transparent, transparent, fill});
g2d.setPaint(rgp);
g2d.fill(new Rectangle(0, 0, mask.getWidth(), mask.getHeight()));
g2d.dispose();
Next, we use a AlphaComposite to paint the mask over the original (city) image...
BufferedImage masked = new BufferedImage(city.getWidth(), city.getHeight(), BufferedImage.TYPE_INT_ARGB);
g2d = masked.createGraphics();
g2d.setColor(Color.RED);
g2d.fillRect(0, 0, masked.getWidth(), masked.getHeight());
g2d.drawImage(city, 0, 0, null);
g2d.setComposite(AlphaComposite.DstAtop);
g2d.drawImage(mask, 0, 0, null);
g2d.dispose();
This generates something like...
The "white" hole is actually transparent, it's just the page is also white :/
Finally, we combine the masked image with the background image...
BufferedImage composite = new BufferedImage(city.getWidth(), city.getHeight(), BufferedImage.TYPE_INT_ARGB);
g2d = composite.createGraphics();
g2d.drawImage(background, city.getWidth() - background.getWidth(), 0, null);
g2d.drawImage(masked, 0, 0, null);
g2d.dispose();
to produce something like...
So, based on your description, this is what I assume you mean

From here:
# import the necessary packages
from __future__ import print_function
import numpy as np
import cv2
# load the image
image = cv2.imread("pic.jpg")
# loop over the alpha transparency values
for alpha in np.arange(0, 1.1, 0.1)[::-1]:
# create two copies of the original image -- one for
# the overlay and one for the final output image
overlay = image.copy()
output = image.copy()
# draw a red rectangle surrounding Adrian in the image
# along with the text "PyImageSearch" at the top-left
# corner
cv2.rectangle(overlay, (420, 205), (595, 385),
(0, 0, 255), -1)
cv2.putText(overlay, "PyImageSearch: alpha={}".format(alpha),
(10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), 3)
# apply the overlay
cv2.addWeighted(overlay, alpha, output, 1 - alpha,
0, output)
# show the output image
print("alpha={}, beta={}".format(alpha, 1 - alpha))
cv2.imshow("Output", output)
cv2.waitKey(0)

Related

Combine multiple graphics2d composites?

How can i combine 2 composites in to one? Let me explain:
BufferedImage copy = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = copy.createGraphics();
g2d.setComposite(AlphaComposite.Clear);
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
Now we have a transparent image.
g2d.setComposite(AlphaComposite.Src);
g2d.drawImage(img, 0, 0, null);
Now we have an exact copy of the "img" including the transparent areas.
g2d.setComposite(BlendComposite.getInstance(BlendingMode.MULTIPLY));
g2d.setColor(overlayColor);
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
(BlendComposite from http://www.curious-creature.com/2006/09/20/new-blendings-modes-for-java2d/)
At this point the the multiply composite has given the image a nice color (overlayColor).
But the transparent areas now have the same color as overlayColor.
How can i prevent the transparent area's from getting the overlayColor?
#haraldK point me to a nice working solution:
Paint the original (img) over the copy (using the existing g2d) with
DstIn AlphaComposite?
I gave it a try just after the multiply step:
g2d.setComposite(AlphaComposite.DstIn);
g2d.drawImage(img, 0, 0, null);
And it now works, i have my transparency back!
For anyone with the same problem:
AlphaComposite.DstIn:
If pixels in the source and the destination overlap, the alpha from the source is applied to the destination pixels in the overlapping area. If the alpha = 1.0, the pixels in the overlapping area are unchanged; if the alpha is 0.0, pixels in the overlapping area are cleared.
http://docs.oracle.com/javase/tutorial/2d/advanced/compositing.html

Creating an Image that is completely transparent

I want to create an Image object which is absolutely transparent. The JFrame method
createImage(int x, int y);
is totally useless, because it creates a white rectangle, not a transparent one. In the past, I loaded in a PNG file that was transparent, but there must be a simpler way to do it.
Have you looked at BufferedImage? It is a base class for working with images in standard java. It supports ARGB image types that includes alpha channel (transparency) along with standard RGB.
You can try something like this to create transparent image:
BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
Graphics gr = image.getGraphics();
gr.setColor(new Color(0, 0, 0, 0)); // last component is alpha channel.
// 0 - transparent, 255 - opaque
gr.fillRect(0, 0, 100, 100):
// Now image is transparent
I didn't test it but it should work.

How do I set the background of a dynamically created BufferedImage instance to transparent?

I am trying to create a BufferedImage instance which contains a rounded rectangle of a certain colour and is transparent everywhere else.
I am using the following code to create the image
private BufferedImage createChromImage() {
BufferedImage I = new BufferedImage(350, 20, ColorSpace.TYPE_RGB);
Graphics2D g2 = I.createGraphics();
g2.setPaint(new GradientPaint(0, 0, Color.DARK_GRAY, 100,
100, Color.BLUE, false));
g2.fillRoundRect(0, 0, 350, 20, 10, 10);
return I;
}
I end up with a rounded rectangle on a black background, is there a way in which I can get it on a transparent background. I suspect it will require a different ColorSpace setting, but I not sure which.. any help is much appreciated.
You can't have a transparent background in an image that does not support transparency. RGB is a 24-bit image with no transparency. Instead, you want to use BufferedImage.TYPE_INT_ARGB as the argument to BufferedImage's constructor: that will give you an alpha channel to play with, which will allow transparency.

BufferedImage INT / 4BYTE / USHORT

I know the difference in memory usage between byte, unsigned short, and integer, but when it comes to a BufferedImage, is there a 'speed' difference between them?
I have been using the Image type in my code to store images, but I require an alpha layer. Using BufferedImage provides me with ARGB, but my code is /considerably/ slower after making the change from the Image type (and it was only changed for a few objects), so I'm looking for all the performance improvement I can get.
I'm not sure how stupid of a question this may be, so I thank you in response for any replies.
Tanaki,
I have found that, when in need of using an alpha channel in a BufferedImage, the best is to premultiply the alpha channel. For example:
// Create an ARGB image
BufferedImage bi = new BufferedImage(512, 512, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bi.createGraphics();
// Fill the background (for illustration)
g.setColor(Color.black);
g.fill(new Rectangle(0, 0, 512, 512));
AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f));
// Keep the original composite
Composite original = g.getComposite();
g.setComposite(alpha);
// Paint with transparency
Rectangle r = new Rectangle(100, 200, 50, 50);
g.setColor(Color.magenta);
g.fillRect(r);
g.setComposite(original);
// ... paint further shapes or images as necessary
// ...
g.dispose();
// Convert to a premultiplied alpha image for fast painting to a Canvas
BufferedImage biPre = new BufferedImage(512, 512, BufferedImage.TYPE_INT_ARGB_PRE);
Graphics2D gPre = biPre.createGraphics();
gPre.drawImage(bi, 0, 0, null);
gPre.dispose();
// clean up:
bi.flush();
// Now use biPre for painting to a Canvas, or a Component.
// ...
// Remember to flush it when done!
biPre.flush();
The reason for painting first to a TYPE_INT_ARGB is to ensure that all alpha gets painted as you expected (not pre-multiplied every time!). Then, when done, paint the whole image onto a TYPE_INT_ARGB_PRE, which is then able to bring the data to the screen with good speed.

Java padding image

I am working on creating an online image editing tool.Looking for some refernce how can I add an image with white space on right side.For example see this image
Presumably, you want to create a new image from an existing image, where the new image has white space on the left and right?
Suppose the unpadded image was a BufferedImage and is called 'image'. Suppose the amount of whitespace you want on each side is 'w'. What you want to do is create a new BufferedImage wider than the original, then paint the entire thing white, and finally draw the smaller image on top of it:
BufferedImage newImage = new BufferedImage(image.getWidth() + 2 * w, image.getHeight(), image.getType());
Graphics g = newImage.getGraphics();
g.setColor(Color.white);
g.fillRect(0, 0, image.getWidth() + 2 * w, image.getHeight());
g.drawImage(image, w, 0, null);
g.dispose();
If anyone comes upon a similar problem, I would definitively recommend imgScalr. You can add padding with literally one line imageSource= Scalr.pad(imageSource,pad,Color.White);.
Create a new BufferedImage object of the right size; use Graphics.fillRect() to paint it white; draw the image into the top-left corner with drawImage(); then save your new image.

Categories