JavaFX ImageView没有任何平滑

javafx javafx-2

9375 观看

4回复

420 作者的声誉

是否可以在JavaFX 2.2中的ImageView中渲染缩放图像而不应用任何平滑?我正在使用setSmooth(false)将50x50图像渲染到200x200 ImageView中,因此源图像中的每个像素都应映射到屏幕上的4x4正方形。

但是,生成的渲染仍然可以平滑所有16个目标像素上的源像素。有没有人知道如何在不手动将每个像素复制到新图像的情况下执行此操作?

作者: ajselvig 的来源 发布者: 2013 年 4 月 18 日

回应 (4)


24

114577 作者的声誉

决定

在JavaFX 2.2 ImageView中总是会做一些平滑,无论你提供的平滑提示如何ImageView

(基于使用Java 7u15和带有ATI HD4600显卡的Windows 7进行测试)。

也许这是一个ImageView总是能够平滑的错误Image,但是文档并没有真正指定平滑做什么或不做什么,所以很难说它的真正意图是什么。您可能希望将此问题的引用发布到openjfx-dev邮件列表,或者在JavaFX问题跟踪器中记录问题以获得开发人员的更专家意见。


我尝试了一些不同的方法来缩放图像:

  1. Image构造函数中缩放。
  2. 规模ImageViewfitWidth / fitHeight
  3. 使用scaleX / scaleY属性进行缩放ImageView
  4. 通过Image使用PixelReader进行采样并使用PixelWriter创建新图像进行缩放

我发现方法1和4导致了一个像素图像的锐利像素,而2和3导致模糊的混叠图像。

机器人采样

用于生成上述输出的示例代码


更新有关实施您自己的图像过滤器的想法

JavaFX效果与用于图像加载例程的过滤器不同,但可以创建过滤图像的效果。在JavaFX 2.2公开记录的API中,支持创建自定义效果,因此创建自定义效果可能会很困难。

图像支持的机代码最近是作为openjfx项目的一部分开源的,因此您可以查看它以了解当前如何实现过滤。

您可能还希望针对JavaFX运行时项目提交功能请求,以“允许我们创建自己的2D过滤器”。

作者: jewelsea 发布者: 18.04.2013 08:38

3

211 作者的声誉

我知道这有点老了,但我最近需要这样的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然而,为什么不能简单地将“平滑”标志传递给纹理的线性过滤设置。

作者: Martin Sojka 发布者: 02.09.2016 02:13

0

73 作者的声誉

当您将以下构造函数添加到Martin Sojka的答案时,您只需将javafx Image传递给构造函数即可。尽管有关于已弃用功能的警告,但他的答案仍然可以正常工作(在JDK 1.8_121上)。

public PixelatedImageView (javafx.scene.image.Image image) {
    super(image);
}
作者: Lappro 发布者: 03.04.2017 06:57

0

1 作者的声誉

如果有人在Java 9或更高版本中遇到同样的问题,这里是Martin Sojka解决方案的编辑版本,该解决方案使用反射来访问现在的一些私有成员ImageView

import java.lang.reflect.InvocationTargetException;

import javafx.scene.Node;
import javafx.scene.image.ImageView;

import com.sun.javafx.geom.BaseBounds;
import com.sun.javafx.geom.transform.BaseTransform;
import com.sun.javafx.scene.ImageViewHelper;
import com.sun.javafx.sg.prism.NGImageView;
import com.sun.javafx.sg.prism.NGNode;
import com.sun.prism.Graphics;
import com.sun.prism.Image;
import com.sun.prism.Texture;
import com.sun.prism.impl.BaseResourceFactory;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.commons.lang3.reflect.MethodUtils;

public class PixelatedImageView extends ImageView {

    public PixelatedImageView(javafx.scene.image.Image image) {
        super(image);

        try {
            initialize();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    private void initialize() throws IllegalAccessException {
        Object nodeHelper = FieldUtils.readField(this, "nodeHelper", true);
        FieldUtils.writeField(nodeHelper, "imageViewAccessor", null, true);
        ImageViewHelper.setImageViewAccessor(new ImageViewHelper.ImageViewAccessor() {
            @Override
            public NGNode doCreatePeer(Node node) {
                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);
                    }
                };
            }

            @Override
            public void doUpdatePeer(Node node) {
                try {
                    MethodUtils.invokeMethod(node, "doUpdatePeer");
                } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public BaseBounds doComputeGeomBounds(Node node, BaseBounds bounds, BaseTransform tx) {
                try {
                    return (BaseBounds) MethodUtils.invokeMethod(node, "doComputeGeomBounds", bounds, tx);
                } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                    return null;
                }
            }

            @Override
            public boolean doComputeContains(Node node, double localX, double localY) {
                try {
                    return (boolean) MethodUtils.invokeMethod(node, "doComputeContains", localX, localY);
                } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                    return false;
                }
            }
        });
    }

}
作者: Calabiyaur 发布者: 09.07.2019 08:21
32x32