Could someone explain why this line of code isn't working. No errors are given. It simply doesn't resize the image.
image = ImageIO.read(file);
image.getScaledInstance(ImageDisplayBox.getWidth(), ImageDisplayBox.getHeight());
ImageDisplayBox.setIcon(new ImageIcon(image));
I've looked at the other answers on Stackoverflow and noticed a lot of people using the .getScaledInstance method.
I (think) it might be the fact that I have it as .setIcon - Although I'm not the best with Java.
The image is printed but displays only the top left of the image due to size.
You're ignoring the returned value. You want:
image = image.getScaledInstance(ImageDisplayBox.getWidth(),
ImageDisplayBox.getHeight(), 5);
Or maybe to make things clearer:
Image scaled = image.getScaledInstance(ImageDisplayBox.getWidth(),
ImageDisplayBox.getHeight(), 5);
ImageDisplayBox.setIcon(new ImageIcon(scaled));
From the docs:
Creates a scaled version of this image. A new Image object is returned which will render the image at the specified width and height by default. The new Image object may be loaded asynchronously even if the original source image has already been loaded completely.
Note that that doesn't say anything about changing the existing image. It just creates a new image with the given size.
Yes
This should work
Image scaled =image.getScaledInstance(ImageDisplayBox.getWidth(),
ImageDisplayBox.getHeight(), 5);
ImageDisplayBox.setIcon(new ImageIcon(scaled));
Related
So here is the problem: I am loading an image which is of unknown resolution. I need to scale it to 500px width to fit within my UI, preserving aspect ratio. The image quality must be good as i need to use it later, specifically to calculate an angle between two objects within the image.
So far i have tried the following:
In the following examples, we have an existing UI element ImageView imageView;
Method one: using scale on load in JavaFX image constructor:
public void setImage(String path){
Image image = new Image(path, 550, 412, true, true);
imageView.setImage(image);
}
This method achieves the required scaling, but lacks the quality required for an accurate calculation of angle later on.
Method two: using ImageView scaling to scale the displayed image:
public void setImage(String path){
Image image = new Image(path);
imageView.setFitWidth(550);
imageView.setPreserveRatio(true);
imageView.setImage(image);
}
This achieves the required quality and scaling, but the image contained within the view is not actually scaled, which means the calculations done later down the line are using an image not representative of the one being displayed.
Is there a way i can alter either of these solutions to work better or is there a better approach i can take? thank you.
You will have to use,
imageView.setSmooth(true);
to achieve better quality image after scaling.
EDIT:
It is because, the two methods are essentially different. The first method loads a bad quality image in the first place (with lesser pixels). One thing you can try is, to use AWT Image class for loading the image, using ImageIO, and call scaledImage = image.getScaledInstance(width, height). Then use something like (pseudo code):
create bufferedImage of scaled size
bufferedImage.createGraphics()
.drawImage(scaledImage, 0, 0, null)
to get scaled AWT Image. Then use SwingFXUtils to convert to image for FX application. This whole thing can probably be done in 3 lines of code by chaining the methods. I was able to achieve better quality this way in one of my previous projects.
I was trying to do really the same functionality of resizing images like in MS Word.
I want to resize BufferedImage but I’m losing some information during process of resizing.
I tried to implement two approaches, but both produced same result.
Before any resizing:
Picture after few resize actions in my application:
First approach:
image = Thumbnails.of(image).size(w,h).asBufferedImage();
Second approach:
image = toBufferedImage(image.getScaledInstance(w, h, Image.SCALE_SMOOTH));
image is instance of BufferedImage, w is new width of image and h is new hight of image
Any idea, what I’m doing wrong?
You're constantly losing information from your image after each resizing attempt. If you want solution (like in MS Word) you have to keep somewhere original image but show only resized copy.
The best solution would be creating an object to store original image and making resized copy on demand. You can improve quality of this solution adding simple cache so you don't actually generate another resized copy of your image for every request but only if your application demands image with different height or width than last time.
I hope I helped you a bit.
I'm trying to read, rescale and save images within a Servlet. That's the relevant code:
BufferedImage image = ImageIO.read(file);
BufferedImage after = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
AffineTransform at = AffineTransform.getScaleInstance(factor, factor);
AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
after = scaleOp.filter(image, null);
ImageIO.write(after, "JPG", file));
The original file is a plain RGB-Jpeg, but when I open and save the file it comes out as a CMYK-Jpeg. That happens even if i don't rescale the image, just opening and closing the image causes the problem.
When I open PNGs or GIFs everything is fine. Does anybody know what to do here? I would expect ImageIO's read-Method to retain the original colorspace.
If there's another way comfortable way of reading jpeg's?
Thanks for any suggestions!
You create after and then overwrite it with scaleOp.filter. Is this correct? So your after image may not be RGB even though you think it is? If you want after to be RGB then you may need to 'draw' image onto after before you do the transform.
I have had the same problem, and found this page.
I tried the suggestion above of creating a BufferedImage with the right type and using it as the after image instead of null in the filter call; and that did indeed resolve the problem.
ImageIO.read ignores all embedded metadata, including an embedded color profile, which defines how RBG values map to physical devices such as screens or printers.
You could read the metadata separately and pass it to ImageIO.write, but it's easier to just convert the image to the (default) sRGB color space and ignore the metadata.
If you don't mind losing the metadata, replace
after = scaleOp.filter(image, null);
with
after = scaleOp.filter(image, after);
From the documentation of AffineTransformOp.filter:
If the color models for the two images do not match, a color conversion
into the destination color model is performed.
hy,
I've a little probleme with a graphics. I've an image witch I resize like this :
Image BigImage = img.getScaledInstance(115, 154, java.awt.Image.SCALE_SMOOTH);
and I tried ti draw it on a graphic:
g2.drawImage(BigImage, 0, 0, null);
it's unfortunately not working.
it only work if i add ImageIcon te = new ImageIcon(BigImage);
Image BigImage = img.getScaledInstance(115, 154, java.awt.Image.SCALE_SMOOTH);
ImageIcon te = new ImageIcon(BigImage);
g2.drawImage(BigImage, 0, 0, null);
Do you have any idea why? Have you another way to do it?
I can't say right now why your code doesn't work, but you can directly draw a scaled instance of the image using this drawImage method. It worked for me.
The documenttion for Image.getScaledInstance() states in part..
The new Image object may be loaded asynchronously even if the original source image has already been loaded completely.
(My emphasis)
One way to correct the problem is to add the image to a MediaTracker to ensure it is loaded before rendering. But most importantly, do not do any of this from within the paint()/paintComponent() method, which is what I suspect given the code snippet. The instantiation of the ImageIcon was probably slowing down the execution just enough for the image to load.
Another tip I will offer is that you will get better help sooner if you post an SSCCE. This is particularly useful for image based examples, since if you'd hot-linked to an image available on the net, we could've seen just how big the image was that was being rescaled. ;)
i'm trying to create a program that generates images for use as multi-screen backgrounds, i'm doing this targeted at windows (in my case, 7 so that basically i can get images to change without seeing the same image on two different screens)
in my program, i read multiple image input files and compile them into a single output image that is the total size of the desktop (including black areas not seen on screens)
my question is, what class/methods are good for cropping/resizing/pasting into a new image in java because i'm coming across so many image manipulation classes and they all seem to do one tiny thing.
i will not be modifying any of the images beyond resize or crop and putting it into a certain position in the new (initially blank) image.
code can be made available as i plan to release it at some later point for whoever may like/need it.
thank you in advance, if this question has been answered, my apologies but i DID have a look around.
I do not know if this is the best method, but it is quite easy:
// load an image
Image image = javax.imageio.ImageIO.read(new File("someimage.png");
// resize it
image = image.getScaledInstance(100, 100, Image.SCALE_SMOOTH);
// create a new image to render to
BufferedImage newimg = new BufferedImage(200,100,BufferedImage.TYPE_INT_ARGB);
// get graphics to draw..
Graphics2D graphics =newimg.createGraphics();
//draw the other image on it
graphics.drawImage(image,0,0,null);
graphics.drawImage(image,100,0,null);
graphics.fillOval(20,20,40,40); //making it a bit ugly ;)
//export the new image
ImageIO.write(newimg,"png",new File("output.png"));
//done!
For simplicity I dropped all checks, exception handling, etc.