JavaFX canvas api 使用字节数组和PixelFormat来写入图像

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.PixelFormat;
import javafx.scene.image.PixelWriter;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

import java.nio.ByteBuffer;

import static javafx.application.Application.launch;

/**
 * @author zhaoyong
 * @Date 2022/1/6
 * @Description
 */
public class ImageOps extends Application {
    // 图像数据
    private static final int IMAGE_WIDTH = 10;//设置图像的宽度
    private static final int IMAGE_HEIGHT = 10;//设置图像的长度
    private byte imageData[] =
            new byte[IMAGE_WIDTH * IMAGE_HEIGHT * 3];//创建一个字节型数组

    // 绘制表面 (Canvas)
    private GraphicsContext gc;//创建一个画笔
    private Canvas canvas;//创建一个画布
    private Group root;//创建一个节点组容器

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("PixelWriter测试");
        root = new Group();//初始化节点组容器对象
        canvas = new Canvas(500, 200);//创建衣蛾200*200的宽高画布对象
        canvas.setTranslateX(100);//设置画布对象转变位移X
        canvas.setTranslateY(100);//设置画布对象转变位移Y
        gc = canvas.getGraphicsContext2D();//创建画布上对应的画笔对象
        createImageData();
        drawImageData();
        primaryStage.setScene(new Scene(root, 400, 400));
        primaryStage.show();

    }

    private void createImageData() {//创建一个图片图形
        int i = 0;
        for (int y = 0; y < IMAGE_HEIGHT; y++) {
            int r = y * 255 / IMAGE_HEIGHT;
            for (int x = 0; x < IMAGE_WIDTH; x++) {
                int g = x * 255 / IMAGE_WIDTH;
                imageData[i] = (byte) r;
                imageData[i + 1] = (byte) g;
                i += 3;
            }
        }
    }

    private void drawImageData() {
        boolean on = true;
        PixelWriter pixelWriter = gc.getPixelWriter();//创建一个像素写入器
        PixelFormat<ByteBuffer> pixelFormat = PixelFormat.getByteRgbInstance();//创建一个像素格式
        for (int y = 50; y < 150; y += IMAGE_HEIGHT) {
            for (int x = 50; x < 150; x += IMAGE_WIDTH) {
                if (on) {
                    pixelWriter.setPixels(x, y, IMAGE_WIDTH,
                            IMAGE_HEIGHT, pixelFormat, imageData,
                            0, IMAGE_WIDTH * 3);
                }
                on = !on;
            }
            on = !on;
        }

        // 增加阴影效果
        gc.applyEffect(new DropShadow(20, 20, 20, Color.GRAY));
        root.getChildren().add(canvas);//节点容器组添加画布
    }
}

 

这个Demo没有从已有的图片中读取数据,它完全从零开始创建了一个新的WritableImage对象。它绘制了几行带有多种颜色的10*10的矩形,对应的颜色数据被存储在一个像素数组中,表示每个像素的RGB值 

 两个私有方法createImageData和drawImageData,createImageData方法设置了在每个10*10的矩形中的颜色的RGB值

 ________________________________________

创建一个快照

javafx.scene.Scene类还提供了一个snapshot方法,它返回一个WritableImage,其中包含了当前展示在你的应用程序场景中内容。当与Java中的ImageIO类配合使用时,你可以将快照存储到文件系统中

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.PixelFormat;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javax.imageio.ImageIO;

public class ImageTest extends Application {

    // 图像数据
    private static final int IMAGE_WIDTH = 10;//图片宽度
    private static final int IMAGE_HEIGHT = 10;//图片高度
    private byte imageData[] = new byte[IMAGE_WIDTH * IMAGE_HEIGHT * 3];//创建图形数据字节数组
    // 绘制表面 (Canvas)
    private GraphicsContext gc;//创建画笔
    private Canvas canvas;//创建画布
    private Group root;//创建节点组容器对象

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("PixelWriter Test");//设置舞台标题
        root = new Group();//初始化节点组对象
        canvas = new Canvas(200, 200);//初始化创建画布
        canvas.setTranslateX(100);//设置画布位移X
        canvas.setTranslateY(100);//设置画布位移Y
        gc = canvas.getGraphicsContext2D();//获取画布上的画笔对象
        createImageData();//创建图形数据
        drawImageData();//绘画图形

        Scene scene = new Scene(root, 400, 400);//创建场景
        primaryStage.setScene(scene);//舞台设置场景
        primaryStage.show();//舞台展现

        // 截取场景的快照
        WritableImage writableImage = scene.snapshot(null);//获取场景图像的快照图片

        // 将快照作为png图像写入到文件系统中
        File outFile = new File("imageops-snapshot.png");//相对程序所在的当前目录创建一个文件对象
        try {//将快照写入文件系统存为.png图片
            ImageIO.write(SwingFXUtils.fromFXImage(writableImage, null),
                    "png", outFile);//利用图片文件输出流工具将文件写出去并保存到指定目录下
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
    }

    private void createImageData() {
        int i = 0;
        for (int y = 0; y < IMAGE_HEIGHT; y++) {
            System.out.println("y: " + y);
            int r = y * 255 / IMAGE_HEIGHT;
            for (int x = 0; x < IMAGE_WIDTH; x++) {
                System.out.println("\tx: " + x);
                int g = x * 255 / IMAGE_WIDTH;
                imageData[i] = (byte) r;
                imageData[i + 1] = (byte) g;
                System.out.println("\t\tR: " + (byte) r);
                System.out.println("\t\tG: " + (byte) g);
                i += 3;
            }
        }
        System.out.println("imageData.lengthdrawImageData: " + imageData.length);
    }

    private void drawImageData() {
        boolean on = true;
        PixelWriter pixelWriter = gc.getPixelWriter();
        PixelFormat<ByteBuffer> pixelFormat = PixelFormat.getByteRgbInstance();
        for (int y = 50; y < 150; y += IMAGE_HEIGHT) {
            for (int x = 50; x < 150; x += IMAGE_WIDTH) {
                if (on) {
                    pixelWriter.setPixels(x, y, IMAGE_WIDTH,
                            IMAGE_HEIGHT, pixelFormat,
                            imageData, 0, IMAGE_WIDTH * 3);
                }
                on = !on;
            }
            on = !on;
        }

        // 增加阴影效果
        gc.applyEffect(new DropShadow(20, 20, 20, Color.GRAY));//设置阴影特效
        root.getChildren().add(canvas);//节点组上添加画布对象
    }
}

说明:

调用scene.snapshot(null)创建了一个场景对象的新的快照并将其分配给了新构建的WritableImage。然后(在ImageIO和SwingFXUtils的帮助下)这个图片被写入文件系统并保存为了一个.png图片

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Canvas APIJavaFX中用于绘制图形的一个强大的工具,它可以让你以像素为单位绘制形状、线条、文本和图像,并且可以使用不同的绘图属性来控制渲染。如果你想要清晰地绘制图形,那么使用Canvas API可以让你轻松实现。 以下是使用Canvas API进行清晰绘图的几个技巧: 1. 使用高分辨率的Canvas 在创建Canvas对象时,可以指定它的宽度和高度。如果你需要绘制的图形很复杂,或者需要绘制的图形比较大,那么可以使用高分辨率的Canvas来保证图形的清晰度。例如,如果你需要绘制一个1000x1000像素的图形,那么可以这样创建Canvas对象: ``` Canvas canvas = new Canvas(1000, 1000); ``` 2. 使用反锯齿 反锯齿可以让图形的边缘更加平滑,从而使图形看起来更加清晰。你可以通过设置Canvas对象的antiAliasing属性来启用反锯齿: ``` canvas.setAntiAliasing(true); ``` 3. 使用线性插值 线性插值可以让图形的颜色更加平滑,从而使图形看起来更加清晰。你可以通过设置Canvas对象的interpolation属性来启用线性插值: ``` canvas.setInterpolation(Interpolation.LINEAR); ``` 4. 使用高质量的渲染模式 Canvas API支持多种渲染模式,包括DEFAULT、QUALITY和SPEED。QUALITY模式可以提供最高质量的渲染,从而使图形看起来更加清晰。你可以通过设置Canvas对象的rendering属性来启用高质量的渲染模式: ``` canvas.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); ``` 使用这些技巧可以让你轻松实现清晰的绘图效果,并且可以为你的应用程序增加一些视觉上的吸引力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值