JavaFX: maximum ImageView size - javafx

This may sound like a duplicate of Set maximum size for JavaFX ImageView but it's different.
I'd like to restrict the maximum size of an ImageView. Unfortunately, the only way to set the ImageView's size seems to be fitWidth and fitHeight which however enlarges the image if it's smaller than the fit values.
I tried setting fitWidth/fitHeight to 0/0 and wrap the ImageView into a pane with maxWidth set - no success (image is displayed in original size).
To me it seems as this is not achievable by JavaFX, however I can't believe it. But I couldn't find anything online. Are there any tricks/bugs/workarounds on this?

If you dont want the image to stretch, you can use:
setPreserveRatio(true);
Then you are able to fit width and height as you want
ImageView setPreserveRatio javadoc
In javadoc in this method there are the rules of scaling too

You just needed to add in if statement to set those larger than maxsize to a fixed size. The rest would remain their original size.
ImageView im = new ImageView();
im.setImage(image);
im.maxHeight(690 - 10);
int yoursize = 690;
if(im.maxHeight(690 - 10)> yoursize ){
im.setFitHeight(690- 10);
System.out.println("Fix Size : 690 ");
}
im.setPreserveRatio(true);
im.setSmooth(true);
im.setCache(true);

You can get the actual Image resource and query its width/height to use for the fit values:
Image image = imageView.getImage();
double nativeWidth = image.getWidth();
double nativeHeight = image.getHeight();

Related

Resizing ImageViews

I have a GridPane (4x5), all it's cells have as child an AnchorPane which cointains an ImageView. I need to resize the image so it fully cover the cell as soon as the gridPane (and thus it's cells) change size.
I managed to resize the image correctly when the size of the cell grows, but when the cell gets tinier the image doesn't resize back.
This leads into partially covering images of the confinant cells.
Can anyone explain what i'm doing wrong or give me the instruction to implement a proper resize?
This is my code:
ImageView image = new ImageView("/dice/" + draftList.get(i) + ".png");
AnchorPane pane = ((AnchorPane)(gridpane.getChildren().get(i)));
pane.getChildren().add(image);
fitToParent(image,pane);
//method in the same class
private void fitToParent(ImageView image, AnchorPane pane) {
image.fitWidthProperty().bind(pane.widthProperty());
image.fitHeightProperty().bind(pane.heightProperty());
}
You can try to use the setPreserveRatio(boolean) function of the ImageView class to true. This will allow you to keep the aspect ratio constant.
Eg:
ImageView iv = new ImageView(/*file path*/);
iv.setPreserveRatio(true);
Src: https://docs.oracle.com/javase/8/javafx/api/javafx/scene/image/ImageView.html
Other than this you can also try to limit the resizable property to false or set the min width and height so that the image is not partially covered
Src: https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/Region.html#resize-double-double-

JavaFX get minimum width/height/size of a Pane before it starts clipping

FFor the sake of simplicity it is better to show you the problem and then describe it
I plan to set the minimum width of the window to the minimum size possible before the pane (groupPane in this example) starts being clipped
how can i calculate that width beforehand.
the fxml section :
the current calculation method:
public void setupMinStageSizeInStandardMode(Stage primaryStage, Scene scene)
{
// the thickness of the border of the window
ObjectBinding<Insets> insets = Bindings.createObjectBinding(() ->
new Insets(scene.getY(),
primaryStage.getWidth()-scene.getWidth() - scene.getX(),
primaryStage.getHeight()-scene.getHeight() - scene.getY(),
scene.getX()),
scene.xProperty(),
scene.yProperty(),
scene.widthProperty(),
scene.heightProperty(),
primaryStage.widthProperty(),
primaryStage.heightProperty()
);
//i am trying to get the grid to the smallest size here
controlsGrid.setMaxWidth(0);
controlsGrid.setPrefWidth(0);
// then i am trying to calculate the wanted size
double minStageWidth = controlsGrid.getWidth() +insets.get().getLeft() + insets.get().getRight();
double minStageHeight = controlsGrid.getHeight() +insets.get().getTop() + insets.get().getBottom();
System.out.println(minStageWidth);
System.out.println(minStageHeight);
//then return the grid to it's intended size
controlsGrid.setMaxWidth(Region.USE_PREF_SIZE);
controlsGrid.setPrefWidth(Region.USE_PREF_SIZE);
primaryStage.setMinHeight(minStageHeight);
primaryStage.setMinWidth(minStageWidth);
}
Please help. i am losing sleep over this...

ImageView not resizing image

I want to use an ImageView to resize an image, however the image is not being resized:
ImageView imageView = new ImageView(image);
imageView.setPreserveRatio(true);
imageView.setFitHeight(40);
System.out.println("imageview image width = " + imageView.getImage().getWidth());
System.out.println("imageview image height = " + imageView.getImage().getHeight());
The output is
imageview image width = 674.0
imageview image height = 888.0
However, the width should be 40. My ImageView is not attached to any scene and I also don't want to attach it, it shall only be used for image resizing. Is there any way to force the ImageView to resize its image, even though the ImageView is not attached to any scene? The reason I am using an ImageView for resizing is, that I want to resize an Image in RAM, without reading it again from the disk, please see this question for more details.
Thanks for any hint!
Using an ImageView for resizing seems to be very hacky.
A better approach is to convert your Image into a BufferedImage and do the resizing the old way. (JavaFx does not (yet) provide an internal way to resize memory images)
int width = 500; // desired size
int height = 400;
Image original = ...; // fx image
BufferedImage img = new BufferedImage(
(int)original.getWidth(),
(int)original.getHeight(),
BufferedImage.TYPE_INT_ARGB);
SwingFXUtils.fromFXImage(original, img);
BufferedImage rescaled = Scalr.rescaleImage(img, width, heigth); // the actual rescale
// convert back to FX image
WritableImage rescaledFX = new WritableImage(width, heigth);
SwingFXUtils.toFXImage(rescaled, rescaledFX);
Where as Scalr is a nice library for resizing images in native java. Obviously, you can use other/simpler methods of rescaling, but the image quality won't be that nice.

How can an image be cropped based on a set scale of random image?

Working on allowing the upload of images which can range in a variety of size, then allowing to crop a predefined area of the image for a thumbnail.
The thumbnail size is predefined to 150x150. Using the Jcrop.js tool to select a section of the image.
Problem:
When displaying the uploaded image in a smaller size than the original image by implementing set height/width on the image rendered, then there is a scale factor that comes into play when selecting an area to crop.
You either have to scale down the cropping area proportionately or you have to scale the image in relation to the actual image's size in comparison to its displayed size.
Question:
How do I figure out the scale of the browser displayed image vs. original image? I am currently using the following code to save the image, but how would I take into consideration the scaling?
public static Image CropImage(Image originalImage, int x, int y, int width, int height)
{
var bmp = new Bitmap(width, height);
bmp.SetResolution(originalImage.HorizontalResolution, originalImage.VerticalResolution);
using (var graphic = Graphics.FromImage(bmp))
{
graphic.SmoothingMode = SmoothingMode.AntiAlias;
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphic.PixelOffsetMode = PixelOffsetMode.HighSpeed;
graphic.DrawImage(originalImage, new Rectangle(0, 0, width, height), x, y, width, height, GraphicsUnit.Pixel);
return bmp;
}
}
Bonus Question:
Another problem I discovered, is that there seems to be no efficient way to transfer the original file's ImageFormat when creating a new Bitmap which creates a ImageFormatMemoryBMP and when you attempt to call Bitmap.Save(memorystream, original rawformat) it will blow up. And bitmap RawFormat has no setter.
So how can you set the format on a new bitmap?
I think perhaps that this problem is solved purely on the front end, no need to use any server side for this.
Jcrop has a built in scale factor handler.
http://deepliquid.com/content/Jcrop_Sizing_Issues.html
Now you can use this in two ways, as I understand it. Either to 'resize' the image for you on the front end using 'box sizing', or you can tell it the 'truesize' of the image and it will work out the scale factor and handle the coordinates for you on it's own.
Box sizing
$('#cropbox').Jcrop({ boxWidth: 450, boxHeight: 400 });
True Size
$.Jcrop('#cropbox',{ trueSize: [500,370] });
Using the true size method you will need to invoke jcrop using the api method:
http://deepliquid.com/content/Jcrop_API.html#API_Invocation_Method
var jcrop_api,
options = { trueSize: [500,370] };
$('#target').Jcrop(options,function(){
jcrop_api = this;
});
Good luck!

GtkToolButton with custom icon but of stock icon size

I've a GtkToolBar which has say 3 GtkToolButtons with each of these having a stock icon value, and hence they all appear in the same size; now I added a 4th GtkToolButton with a custom image (.png), which was of an arbitrary dimension and only this button ended up looking huge (since the image was of higher resolution). What do I do to scale this GtkToolButton to match the other 3 buttons?
Here's the code which does what I briefed about:
GtkWidget *custom_icon = gtk_image_new_from_file(path);
GtkToolItem *toolbar_item = gtk_toggle_tool_button_new();
gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(toolbar_item), custom_icon);
gtk_tool_button_set_label(GTK_TOOL_BUTTON(toolbar_item), "Custom Item");
gtk_toolbar_insert(toolbar, toolbar_item, -1);
Here is another solution.
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(icon_file_path, NULL);
int width, height;
gdk_pixbuf_get_file_info (icon_file_path, &width, &height);
gtk_icon_theme_add_builtin_icon ("custom_icon", width, pixbuf);
g_object_unref (G_OBJECT (pixbuf));
GtkToolItem *toolbar_item = gtk_toggle_tool_button_new();
gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON(toolbar_item), "custom_icon");
If you have the image in different sizes, you can add them all and let Gtk choose the one of the correct size (or resize if not found): Just repeat the first five lines for each of the image files.
You can use your icon anywhere else and its size will also be adjusted automatically.
For example, to use it for your main window:
gtk_window_set_icon_name(GTK_WINDOW(main_window), "custom_icon");
Found it out myself! Here's the trick so that it helps someone like me. Query the icon size from the stock menu item, which is a enum (standard values like GTK_ICON_SIZE_BUTTON, GTK_ICON_SIZE_LARGE_TOOLBAR, etc.). Now get the pixel size using gtk_icon_size_lookup. Create a pixbuf from the custom icon/image file with the right dimensions. Create a GtkImage from that and set it to the new menu item and you're done!
GtkToolItem *stock_menu_item = gtk_toggle_tool_button_new_from_stock(GTK_STOCK_NEW);
GtkIconSize toolbar_icon_size = gtk_tool_item_get_icon_size(stock_menu_item);
gint width = 0, height = 0;
gtk_icon_size_lookup(toolbar_icon_size, &width, &height);
GdkPixbuf *app_icon = gdk_pixbuf_new_from_file_at_size(icon_file_path, width, height, NULL);
GtkImage *tray_icon = gtk_image_new_from_pixbuf(app_icon);
g_object_unref(app_icon);
app_icon = NULL;
GtkToolItem *toolbar_item = gtk_toggle_tool_button_new();
gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(toolbar_item), tray_icon);

Resources