JavaFX ImageView 没有任何平滑
Posted
技术标签:
【中文标题】JavaFX ImageView 没有任何平滑【英文标题】:JavaFX ImageView without any smoothing 【发布时间】:2013-04-11 22:37:38 【问题描述】:是否可以在 JavaFX 2.2 的 ImageView 中呈现缩放图像而不应用任何平滑?我正在使用 setSmooth(false) 将 50x50 的图像渲染成 200x200 的 ImageView,因此源图像中的每个像素都应该映射到屏幕上的 4x4 正方形。
但是,生成的渲染仍然会在所有 16 个目标像素上平滑源像素。有谁知道无需手动将每个像素复制到新图像中的方法?
【问题讨论】:
您可以尝试 Canvas 以获得最大的控制权。 不幸的是,我认为也没有办法在画布中做到这一点。他们真正需要做的是让我们制作自己的 2D 过滤器(我猜它们在 JavaFX 中被称为“效果”)。 用实现自己的图像过滤器的想法更新了我的答案。 【参考方案1】:ImageView 没有修复,但它对我帮助很大。 找了好久,偶然发现了这个帖子:How can I disable antialiasing on a JavaFX Canvas?
为了在画布上绘制图像,从 JavaFX 12 开始可以禁用平滑
canvas.getGraphicsContext2D().setImageSmoothing(false);
【讨论】:
【参考方案2】:当您将以下构造函数添加到 Martin Sojka 的答案时,您可以简单地将 javafx Image 传递给构造函数。此外,尽管有关于已弃用功能的警告,但他的回答仍然可以正常工作(在 JDK 1.8_121 上)。
public PixelatedImageView (javafx.scene.image.Image image)
super(image);
【讨论】:
【参考方案3】:我知道这有点老了,但我最近需要这样的 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
不能简单地将“平滑”标志传递给纹理的线性过滤设置是我无法理解的。
【讨论】:
看起来他们不想让你这样做。 这适用于 Java 8,但看起来这里提到的函数已被重命名并设置为 Java 9 中的私有函数。看起来它不能以相同的方式被覆盖而不进行重大更改ImageView
和 ImageViewHelper
。有人知道如何解决 Java 9 中的新限制吗?
这个答案为我节省了几个小时的工作量......如果 JavaFX 根本不关心它,为什么还有 smooth=false 选项。【参考方案4】:
在 JavaFX 2.2 中,ImageView
总是会进行一些平滑处理,无论您提供给ImageView
的smooth 提示如何。
(基于使用 Java 7u15 和带有 ATI HD4600 显卡的 Windows 7 进行的测试)。
也许ImageView
总是会平滑Image
是一个错误,但文档并没有真正具体说明平滑做什么或不做什么,所以很难说它的真正意图是什么。您可能想在openjfx-dev mailing list 上发布对此问题的引用或在JavaFX issue tracker 中记录问题,以获得开发人员更专业的意见。
我尝试了几种不同的方法来缩放图像:
-
在Image constructor 中缩放。
用fitWidth/fitHeight缩小
ImageView
。
使用ImageView
上的scaleX/scaleY 属性进行扩展。
通过使用PixelReader 对Image
进行采样并使用PixelWriter 创建一个新图像来进行扩展。
我发现方法 1 和 4 会产生您希望的清晰像素化图像,而方法 2 和 3 会产生模糊的混叠图像。
Sample code 生成上述输出。
更新实现您自己的图像过滤器的想法
JavaFX 效果与用于图像加载例程的过滤器不同,尽管可以创建过滤图像的效果。在 JavaFX 2.2 中公开记录的 API 支持创建自定义效果,因此创建自定义效果可能会很困难。
native code for image support 最近作为openjfx project 的一部分开源,因此您可以查看它以了解当前如何实现过滤。
您可能还想提交feature request against the JavaFX runtime project 以“允许我们制作自己的 2D 滤镜”。
【讨论】:
你总是给出如此令人印象深刻的答案jewelsea:D 是的,感谢您的详细回答。我得出了同样的结论,并最终实施了#4。实现本身是微不足道的,但我担心它比 #2 或 #3 慢得多(尽管我还没有验证这一点)。 这个答案已经两年了。有谁知道这是否已在 JavaFX 中修复? 我不确定您所说的固定教育是什么意思。我的猜测是系统的行为符合开发人员的意图。如果您想了解有关在 JavaFX 中过滤和平滑图像的更多信息,您可以按照答案中的说明发布到 open-jfx 开发人员邮件列表。 很奇怪,N° 1. 解决方案对我的 BMP 文件不起作用,它不加载图像,它适用于其他 3 个解决方案,我将使用 N° 4. 解决方案,谢谢。以上是关于JavaFX ImageView 没有任何平滑的主要内容,如果未能解决你的问题,请参考以下文章