Custom JLabel icon - java

I want to use java JLabel with an Icon in custom size on my GUI. like this :
I used this code to change size of original Icon :
ImageIcon imageIcon = (ImageIcon) jLabel1.getIcon();// new ImageIcon( "Play-Hot-icon.png");
ImageIcon thumbnailIcon = new ImageIcon(getScaledImage(imageIcon.getImage(), 25 , 25));
jLabel1.setIcon(thumbnailIcon);
and here is code for resize image
private Image getScaledImage(Image srcImg, int w, int h){
BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = resizedImg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(srcImg, 0, 0, w, h, null);
g2.dispose();
return resizedImg;
}
but after resizing image and using this code the result is this! :
how can I have desired image on my JLabel??
regards,
sajad

The problem is that when you create the scaled image, you use BufferedImage.TYPE_INT_RGB for your new image, and transparency gets rendered as black with just TYPE_INT_RGB.
In order to keep transparency, you need to replace that with BufferedImage.TYPE_INT_ARGB, since you need an alpha component.
However, calling Image.getScaledInstance on imageIcon's image will return a scaled image, already with an alpha component, and you can pass it rendering hints to play with the quality of the scaled image, doing essentially the same as your getScaledImage function, but with less of the hassle.

Related

Scaling BufferedImage and writing to file [duplicate]

I have viewed this question, but it does not seem to actually answer the question that I have. I have a, image file, that may be any resolution. I need to load that image into a BufferedImage Object at a specific resolution (say, for this example, 800x800). I know the Image class can use getScaledInstance() to scale the image to a new size, but I then cannot figure out how to get it back to a BufferedImage. Is there a simple way to scale a Buffered Image to a specific size?
NOTE I I do not want to scale the image by a specific factor, I want to take an image and make is a specific size.
Something like this? :
/**
* Resizes an image using a Graphics2D object backed by a BufferedImage.
* #param srcImg - source image to scale
* #param w - desired width
* #param h - desired height
* #return - the new resized image
*/
private BufferedImage getScaledImage(Image srcImg, int w, int h){
BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TRANSLUCENT);
Graphics2D g2 = resizedImg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(srcImg, 0, 0, w, h, null);
g2.dispose();
return resizedImg;
}
You can create a new BufferedImage of the size you want and then perform a scaled paint of the original image into the new one:
BufferedImage resizedImage = new BufferedImage(new_width, new_height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(image, 0, 0, new_width, new_height, null);
g.dispose();
see this website Link1
Or
This Link2

ImageIO not printing proper color

I am trying to read a PNG image file from disk, draw some rectangles on it and save the modified image on the disk. Here's the scala code:
//l is a list of Rectangle objects of the form (x1,x2,y1,y2)
val image = ImageIO.read(sourceimage);
val graph=image.createGraphics()
graph.setColor(Color.GREEN)
l.foreach(x=>graph.draw(new java.awt.Rectangle(x.x1,x.y1,x.x2-x.x1,x.y2-x.y1)))
graph.dispose()
ImageIO.write(image,"png",new File(destimage))
The rectangles are drawn but in GREY color instead of GREEN. What am I doing wrong?
If the source image is a gray scale image, then it's unlikely that it will be capable of using any color of any sort.
Instead, you need to create a second, colored, BufferedImage and paint the original to it.
BufferedImage original = ImageIO.read(sourceimage);
BufferedImage iamge = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = image.createGraphics();
g2d.drawImage(original, 0, 0, null);
// Continue with what you have
Sorry, I have no experience with PIL, but that's how you'd do it (basically) in pure Java

Add color to a grayscale BufferedImage

Can't find an answer to this, maybe its too basic. I have a gray scale BufferedImage (basically a section from a black-and-white PDF), and I'd like to draw a red box on the image. However, when I do so and save the image, the red box comes out as grey.
How to correctly add color to a gray scale BufferedImage?
I suppose I need to convert the color model(?) from gray scale to RGB? Although I don't need to convert the black and white parts of the image to color - that is to say the resulting image can be black and white. So long as I can draw a red line on the image without it saving as a shade of gray.
The image file is a GIF.
By using the following code, I could add RED rectangle to a grayscale image. See if this works for you. Else let us know what error you faced.
public static void main(String[] args) throws IOException {
BufferedImage old = ImageIO.read(new File("download.gif"));
int w = old.getWidth();
int h = old.getHeight();
BufferedImage img = new BufferedImage(
w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.drawImage(old, 0, 0, null);
g2d.setColor(Color.red);
g2d.drawRect(10, 10, 100, 100);
g2d.dispose();
ImageIO.write(img, "gif", new File("out.gif"));
}

How to make a rounded corner image in Java

I want to make a image with rounded corners. A image will come from input and I will make it rounded corner then save it. I use pure java. How can I do that? I need a function like
public void makeRoundedCorner(Image image, File outputFile){
.....
}
Edit : Added an image for information.
I suggest this method that takes an image and produces an image and keeps the image IO outside:
Edit: I finally managed to make Java2D soft-clip the graphics with the help of Java 2D Trickery: Soft Clipping by Chris Campbell. Sadly, this isn't something Java2D supports out of the box with some RenderhingHint.
public static BufferedImage makeRoundedCorner(BufferedImage image, int cornerRadius) {
int w = image.getWidth();
int h = image.getHeight();
BufferedImage output = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = output.createGraphics();
// This is what we want, but it only does hard-clipping, i.e. aliasing
// g2.setClip(new RoundRectangle2D ...)
// so instead fake soft-clipping by first drawing the desired clip shape
// in fully opaque white with antialiasing enabled...
g2.setComposite(AlphaComposite.Src);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.WHITE);
g2.fill(new RoundRectangle2D.Float(0, 0, w, h, cornerRadius, cornerRadius));
// ... then compositing the image on top,
// using the white shape from above as alpha source
g2.setComposite(AlphaComposite.SrcAtop);
g2.drawImage(image, 0, 0, null);
g2.dispose();
return output;
}
Here's a test driver:
public static void main(String[] args) throws IOException {
BufferedImage icon = ImageIO.read(new File("icon.png"));
BufferedImage rounded = makeRoundedCorner(icon, 20);
ImageIO.write(rounded, "png", new File("icon.rounded.png"));
}
This it what the input/output of the above method looks like:
Input:
Ugly, jagged output with setClip():
Nice, smooth output with composite trick:
Close up of the corners on gray background (setClip() obviously left, composite right):
I am writing a follow up to Philipp Reichart's answer.
the answer of as an answer.
To remove the white background (seems to be black in the pictures), change g2.setComposite(AlphaComposite.SrcAtop);
to g2.setComposite(AlphaComposite.SrcIn);
This was a big problem for me because I have different images with transparency that I don't want to lose.
My original image:
If I use g2.setComposite(AlphaComposite.SrcAtop);:
When I use g2.setComposite(AlphaComposite.SrcIn); the background is transparent.
I found another way using TexturePaint:
ImageObserver obs = ...;
int w = img.getWidth(obs);
int h = img.getHeight(obs);
// any shape can be used
Shape clipShape = new RoundRectangle2D.Double(0, 0, w, h, 20, 20);
// create a BufferedImage with transparency
BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D bg = bi.createGraphics();
// make BufferedImage fully transparent
bg.setComposite(AlphaComposite.Clear);
bg.fillRect(0, 0, w, h);
bg.setComposite(AlphaComposite.SrcOver);
// copy/paint the actual image into the BufferedImage
bg.drawImage(img, 0, 0, w, h, obs);
// set the image to be used as TexturePaint on the target Graphics
g.setPaint(new TexturePaint(bi, new Rectangle2D.Float(0, 0, w, h)));
// activate AntiAliasing
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// translate the origin to where you want to paint the image
g.translate(x, y);
// draw the Image
g.fill(clipShape);
// reset paint
g.setPaint(null);
This code can be simplified if you have a non-animated image, by creating the BufferedImage only once and keeping it for each paint.
If your image is animated though you have to recreate the BufferedImage on each paint. (Or at least i have not found a better solution for this yet.)

Fit Java Image into JFrame

I'm trying to display an Image that is bigger than the JFrame Dimensions. If I try to resize the Image smaller, then the Image quality is lost.
If I make the Image larger, the quality is not lost. Is this normal behavior in Java image package?
I guess what I'm trying to figure out is that probably I'm doing something wrong when reducing the Image size. So does Java provide a method to automatically do this without loosing image quality?
Same behavior like JButtons, where java automatically adjusts the space occupied by a JButton in a JPanel.
bufferedImage = resize(bufImage,500,600);
ImageIcon imageIcon = new ImageIcon(bufferedImage);
resizedIMage = imageIcon.getImage();
The actual resize is below. I took it from the internet.
private static BufferedImage resize(BufferedImage image, int width, int height) {
int type = image.getType() == 0? BufferedImage.TYPE_INT_ARGB : image.getType();
BufferedImage resizedImage = new BufferedImage(width, height, type);
Graphics2D g = resizedImage.createGraphics();
g.setComposite(AlphaComposite.Src);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(image, 0, 0, width, height, null);
g.dispose();
return resizedImage;
}
If you are using Java 5 or newer you can try RenderingHints.VALUE_INTERPOLATION_BICUBIC for your interpolation hint.
There is a very detailed description of the different scaling behaviours of Java2D in this article: perils-of-getScaledInstance
It contains examples of the different downscale results you can expect to see with the different approaches available in Java.
It also provides sample code that uses a multi-step aproach to downscale the image which appears to produce much better results than VALUE_INTERPOLATION_BILINEAR.
Override the paintComponent(Graphics g) method of whatever component will display the image and look at Graphics.drawImage()
You can even cast your Graphics instance into a Graphics2D for more functionalities. For example setRenderingHings()
Graphics2D g2 = (Graphics2D) g;
RenderingHints rh = g2.getRenderingHints ();
rh.put (RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHints (rh);
I would get rid of this:
int type = image.getType() == 0? BufferedImage.TYPE_INT_ARGB : image.getType();
And always use BufferedImage.TYPE_INT_ARGB
That seems to give me good results.

Categories

Resources