JavaFX ImageView没有任何平滑
是否可以在JavaFX 2.2的ImageView中渲染缩放的图像而不应用任何平滑处理? 我正在使用setSmooth(false)将50×50图像渲染到200×200 ImageView中,因此源图像中的每个像素都应该映射到屏幕上的4×4正方形。
然而,所得到的渲染仍然平滑了所有16个目标像素的源像素。 有没有人知道的方法来做到这一点,而不是手动将每个像素复制到一个新的图像?
在JavaFX 2.2中ImageView
总是要做一些平滑处理,而不pipe你提供给ImageView
提示是否平滑 。
(基于使用Java 7u15和Windows 7以及ATI HD4600graphics卡进行的testing)。
也许这是一个错误, ImageView
将永远平滑Image
,但文档并没有真正指定平滑做什么或不做什么,所以很难说真正的意图是什么。 您可能想要将此问题的参考信息发布到openjfx-dev邮件列表或在JavaFX问题跟踪器中logging问题,以获得开发人员的更多专家意见。
我尝试了一些缩放图像的不同方法:
- 在Image构造函数中缩放。
- 使用fitWidth / fitHeight在
ImageView
缩放 。 - 通过在
ImageView
上使用scaleX / scaleY属性进行缩放。 - 通过使用PixelReader对
Image
进行采样并使用PixelWriter创build新图像进行缩放 。
我发现方法1和4导致了一个锐利的像素化图像,如您所愿,2&3导致模糊的别名图像。
示例代码来生成上面的输出。
更新有关实现自己的图像filter的想法
JavaFX效果与用于图像加载例程的滤镜不同,但可以创build用于过滤图像的效果。 在JavaFX 2.2公开logging的API中,支持自定义效果的创build,因此创build自定义效果可能很困难。
图像支持的本地代码最近作为openjfx项目的一部分开源,所以你可以看看如何实现过滤。
您可能还希望针对JavaFX运行时项目提交function请求,以“允许我们制作自己的2D滤镜”。
我知道这是有点老,但我最近有需要这样的ImageView,下面的小黑客正是我想在我的(Windows)机器上。 没有保证,它在任何地方工作。
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); } }; } }
这里的技巧是纹理被重新使用,所以线性过滤设置保持“粘性”。 为什么NGImageView
无法简单地将“平滑”标志传递给纹理的线性过滤设置,这是我的NGImageView
。
当您将以下构造函数添加到Martin Sojka的答案时,您可以简单地将javafx图像传递给构造函数。 同样,尽pipe有关已弃用函数的警告,他的答案仍然正常(JDK 1.8_121)。
public PixelatedImageView (javafx.scene.image.Image image) { super(image); }