如何将 Skija 用于 JavaFX?
How to Use Skija for JavaFX?
如何将 Skija 用于 JavaFX?
这是存储库中的代码示例
Surface surface = Surface.makeRasterN32Premul(100, 100);
Canvas canvas = surface.getCanvas();
Paint paint = new Paint();
paint.setColor(0xFFFF0000);
canvas.drawCircle(50, 50, 30, paint);
但是如何将此 skija canvas 对象转换为 JavaFX 节点?
此答案基于 James_D 使用 byte[]
作为输入流的评论。这是示例代码
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import org.jetbrains.skija.*;
import java.io.ByteArrayInputStream;
public class SkijaFX extends Application{
public static void main(String[] args){
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception{
Surface surface = Surface.makeRasterN32Premul(100, 100);
Canvas canvas = surface.getCanvas();
Paint paint = new Paint();
canvas.drawCircle(50, 50, 30, paint);
Image image = surface.makeImageSnapshot();
Data data = image.encodeToData(EncodedImageFormat.PNG);
byte[] pngBytes = data.getBytes();
ByteArrayInputStream inputStream = new ByteArrayInputStream(pngBytes);
javafx.scene.image.Image imageFx = new javafx.scene.image.Image(inputStream);
ImageView imageView = new ImageView(imageFx);
StackPane root = new StackPane(imageView);
Scene scene = new Scene(root, 300, 300);
primaryStage.setScene(scene);
primaryStage.show();
}
}
更新:
正如mipa所建议的,如果我们使用JavaFX 13及以上版本,而不是使用ByteArrayInputStream
,我们可以使用WritableImage
和PixelBuffer
创建一个ImageView
上述代码的这个变体应该可以更快地进行转换,因为它完全避免了将原始图像数据编码和解码为 PNG 并再次返回。注意:这仅适用于最新的 JavaFX 版本,因为它使用了一些较新的功能。
import org.jetbrains.skija.Canvas;
import org.jetbrains.skija.Image;
import org.jetbrains.skija.Paint;
import org.jetbrains.skija.Surface;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelBuffer;
import javafx.scene.image.PixelFormat;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class SkijaFX extends Application{
public static void main(String[] args){
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception{
Surface surface = Surface.makeRasterN32Premul(100, 100);
Canvas canvas = surface.getCanvas();
Paint paint = new Paint();
canvas.drawCircle(50, 50, 30, paint);
Image image = surface.makeImageSnapshot();
ImageView imageView = new ImageView(new WritableImage(new PixelBuffer<>(image.getWidth(), image.getHeight(), image.peekPixels().asIntBuffer(), PixelFormat.getIntArgbPreInstance())));
StackPane root = new StackPane(imageView);
Scene scene = new Scene(root, 300, 300);
primaryStage.setScene(scene);
primaryStage.show();
}
}
更新:在这个变体中,颜色是错误的。 Skia 的原生图像表示似乎不是 IntArgbPre。 (需要进一步调查。)原始版本通过 PNG 转换避免了此问题。
如何将 Skija 用于 JavaFX?
这是存储库中的代码示例
Surface surface = Surface.makeRasterN32Premul(100, 100);
Canvas canvas = surface.getCanvas();
Paint paint = new Paint();
paint.setColor(0xFFFF0000);
canvas.drawCircle(50, 50, 30, paint);
但是如何将此 skija canvas 对象转换为 JavaFX 节点?
此答案基于 James_D 使用 byte[]
作为输入流的评论。这是示例代码
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import org.jetbrains.skija.*;
import java.io.ByteArrayInputStream;
public class SkijaFX extends Application{
public static void main(String[] args){
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception{
Surface surface = Surface.makeRasterN32Premul(100, 100);
Canvas canvas = surface.getCanvas();
Paint paint = new Paint();
canvas.drawCircle(50, 50, 30, paint);
Image image = surface.makeImageSnapshot();
Data data = image.encodeToData(EncodedImageFormat.PNG);
byte[] pngBytes = data.getBytes();
ByteArrayInputStream inputStream = new ByteArrayInputStream(pngBytes);
javafx.scene.image.Image imageFx = new javafx.scene.image.Image(inputStream);
ImageView imageView = new ImageView(imageFx);
StackPane root = new StackPane(imageView);
Scene scene = new Scene(root, 300, 300);
primaryStage.setScene(scene);
primaryStage.show();
}
}
更新:
正如mipa所建议的,如果我们使用JavaFX 13及以上版本,而不是使用ByteArrayInputStream
,我们可以使用WritableImage
和PixelBuffer
创建一个ImageView
上述代码的这个变体应该可以更快地进行转换,因为它完全避免了将原始图像数据编码和解码为 PNG 并再次返回。注意:这仅适用于最新的 JavaFX 版本,因为它使用了一些较新的功能。
import org.jetbrains.skija.Canvas;
import org.jetbrains.skija.Image;
import org.jetbrains.skija.Paint;
import org.jetbrains.skija.Surface;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelBuffer;
import javafx.scene.image.PixelFormat;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class SkijaFX extends Application{
public static void main(String[] args){
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception{
Surface surface = Surface.makeRasterN32Premul(100, 100);
Canvas canvas = surface.getCanvas();
Paint paint = new Paint();
canvas.drawCircle(50, 50, 30, paint);
Image image = surface.makeImageSnapshot();
ImageView imageView = new ImageView(new WritableImage(new PixelBuffer<>(image.getWidth(), image.getHeight(), image.peekPixels().asIntBuffer(), PixelFormat.getIntArgbPreInstance())));
StackPane root = new StackPane(imageView);
Scene scene = new Scene(root, 300, 300);
primaryStage.setScene(scene);
primaryStage.show();
}
}
更新:在这个变体中,颜色是错误的。 Skia 的原生图像表示似乎不是 IntArgbPre。 (需要进一步调查。)原始版本通过 PNG 转换避免了此问题。