Issue
I have an image saved in my database that is passed to an image as a byte array and then loaded to the Image view. However, I can't get it to fill the imageView. I use the following code:
package com.example.AppPrototipo.ui.tourist;
imports...
@Component
public class ExperienceController {
@FXML
Pane imagePane;
@FXML
ImageView imageViewPrincipal;
private final ExperienceRepository experienceRepository;
public ExperienceController(ExperienceRepository experienceRepository) {
this.experienceRepository = experienceRepository;
}
@FXML
private void initialize(){
Experience experience = experienceRepository.findById(1);
Image image = new Image(new ByteArrayInputStream(experience.getImages().get(0).getImageData()));
imageViewPrincipal.setImage(image);
imageViewPrincipal.fitWidthProperty().bind(imagePane.widthProperty());
imageViewPrincipal.fitHeightProperty().bind(imagePane.heightProperty());
}
}
The desired result would be that the image fills the whole width (fill the black side) by cropping the top and bottom sides and remaining centered. Would anyone be able to help me?
Solution
Assuming you're setting the preserveRatio property to true on the ImageView, and as matt stated is his comment, you only need to set one of them, say fitWidth, and the fitHeight will be calculated using the image ratio.
the problem is that the ratios of the image and the pane don't match so you need to do some cropping using setViewport, and it would be best to do the cropping when the pane's height or width change.
What you need to do is to calculate the ratio of the image, and compare it to the ratio of the pane, the comparison will let you decide whether to keep the original width or original height of the image, and you'll calculate the other using the pane's ratio.
Not really sure if that's the best practice but here's the code for what i have described
double oldImageWidth = image.getWidth(), oldImageHeight = image.getHeight(); //saving the original image size and ratio
double imageRatio = oldImageWidth / oldImageHeight;
imageViewPrincipal.setImage(image);
ChangeListener<Number> listener = (obs, ov, nv) -> {
double paneWidth = imagePane.getWidth();
double paneHeight = imagePane.getHeight();
double paneRatio = paneWidth / paneHeight; //calculating the new pane's ratio
//after width or height changed
double newImageWidth = oldImageWidth, newImageHeight = oldImageHeight;
if (paneRatio > imageRatio) {
newImageHeight = oldImageWidth / paneRatio;
} else if (paneRatio < imageRatio) {
newImageWidth = oldImageHeight * paneRatio;
}
imageViewPrincipal.setViewport(new Rectangle2D( // The rectangle used to crop
(oldImageWidth - newImageWidth) / 2, (oldImageHeight - newImageHeight) / 2, //MinX and MinY to crop from the center
newImageWidth, newImageHeight) // new width and height
);
imageViewPrincipal.setFitWidth(paneWidth);
};
imagePane.widthProperty().addListener(listener);
imagePane.heightProperty().addListener(listener);
And here is how it looks
Answered By - Lukas Owen