Is it possible to render a scaled image in an ImageView in JavaFX 2.2 without any smoothing applied? I'm rendering a 50x50 image into a 200x200 ImageView, with setSmooth(false), so each pixel in the source image should map to a 4x4 square on the screen.
However, the resulting render still smooths the source pixel across all 16 destination pixels. Does anyone know of a way to do this without manually copying over each pixel into a new image?
Image encapsulates the image, itself, and ImageView manages the display of an image. Both classes are packaged in javafx.
JavaFX supports the image formats like Bmp, Gif, Jpeg, Png.
The JavaFX ImageView is a class used for painting images and loading the images with Image class. ImageView class is allowing a user to resize the displayed image by without effecting the aspect ratio and also without effecting the image pixels.
Class ImageView. The ImageView is a Node used for painting images loaded with Image class. This class allows resizing the displayed image (with or without preserving the original aspect ratio) and specifying a viewport into the source image for restricting the pixels displayed by this ImageView .
In JavaFX 2.2 ImageView
is always going to do some smoothing regardless of the smooth hint you provide to the ImageView
.
(Based on testing using Java 7u15 and Windows 7 with an ATI HD4600 graphics card).
Perhaps it is a bug that ImageView
will always smooth the Image
, but the documentation doesn't really specify exactly what smoothing does or doesn't do, so it's hard to say what its real intent is. You may want to post a reference to this question to the openjfx-dev mailing list or log an issue in the JavaFX issue tracker to get a more expert opinion from a developer.
I tried a few different methods for scaling the Image:
ImageView
with fitWidth/fitHeight.ImageView
.Image
with a PixelReader and creating a new Image with a PixelWriter.I found that methods 1 & 4 resulted in a sharp pixelated image as you wish for and 2 & 3 resulted in a blurry aliased image.
Sample code to generate the above output.
Update with ideas on implementing your own image filter
A JavaFX Effect is not the same as the Filter used for the Image loading routines, though an Effect to filter an image could be created. In JavaFX 2.2 publicly documented API to support creation of custom effects, so creating of a custom effect may prove difficult.
The native code for image support was recently open sourced as part of the openjfx project, so you could look at that to see how the filtering is currently implemented.
You may also want to file a feature request against the JavaFX runtime project to "allow us to make our own 2D filters".
I know this is a bit older, but I recently had a need for such ImageView, and the following little hack does exactly what I want on my (Windows) machine. No guarantees that it works everywhere.
import com.sun.javafx.sg.prism.NGImageView;
import com.sun.javafx.sg.prism.NGNode;
import com.sun.prism.Graphics;
import com.sun.prism.Texture;
import com.sun.prism.impl.BaseResourceFactory;
import com.sun.prism.Image;
import javafx.scene.image.ImageView;
@SuppressWarnings("restriction")
public class PixelatedImageView extends ImageView {
@Override protected NGNode impl_createPeer() {
return new NGImageView() {
private Image image;
@Override public void setImage(Object img) {
super.setImage(img);
image = (Image) img;
}
@Override protected void renderContent(Graphics g) {
BaseResourceFactory factory = (BaseResourceFactory) g.getResourceFactory();
Texture tex = factory.getCachedTexture(image, Texture.WrapMode.CLAMP_TO_EDGE);
tex.setLinearFiltering(false);
tex.unlock();
super.renderContent(g);
}
};
}
}
The trick here is that the texture gets re-used, so the linear filtering setting remains "sticky". Why NGImageView
couldn't simply pass the "smooth" flag to the texture's linear filtering setting is beyond me however.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With