且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

无需使用awt即可保存图像

更新时间:2022-06-25 05:08:33

我做了一些更多的研究并做了一个显示错误的例子处理一些方法:

I've done a bit more reasearch and made an example showing the wrong handling of some methods:

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.IntBuffer;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SplitPane;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelReader;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.image.WritablePixelFormat;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javax.imageio.ImageIO;

public class WritableImageDemo extends Application {

  private Image src;
  private int width;
  private int height;
  ImageView srcView;
  ImageView srcView2;
  ImageView srcView3;

  @Override
  public void start(Stage primaryStage) {
    primaryStage.setTitle("Image");

    src = new Image("http://www.gnu.org/graphics/gnu-head.jpg");
    width = (int) src.getWidth();
    height = (int) src.getHeight();

    srcView = new ImageView(src);
    srcView2 = new ImageView();
    srcView3 = new ImageView();

    ScrollPane scrollPane = new ScrollPane();
    ScrollPane scrollPane2 = new ScrollPane();
    ScrollPane scrollPane3 = new ScrollPane();

    scrollPane.setContent(srcView);
    scrollPane2.setContent(srcView2);
    scrollPane3.setContent(srcView3);

    SplitPane root = new SplitPane(scrollPane, scrollPane2, scrollPane3);

    primaryStage.setScene(new Scene(root, 800, 600));
    primaryStage.show();

    srcView2.setImage(writeToFile());
  }

  private WritableImage writeToFile() {
    WritableImage insert = new WritableImage(width, height);
    WritableImage newimage = new WritableImage(width, height);

    SnapshotParameters parameters = new SnapshotParameters();
    parameters.setFill(Color.TRANSPARENT);
    // make a snapshot
    srcView.snapshot(parameters, insert);

    PixelReader reader = insert.getPixelReader();
    PixelWriter writer = newimage.getPixelWriter();
    WritablePixelFormat<IntBuffer> format = WritablePixelFormat.getIntArgbInstance();

    System.out.println("WritablePixelFormat.getType(): " + format.getType());
    // the following normally creates an exact copy of the original
    for (int x = 0; x < width; x++) {
      for (int y = 0; y < height; y++) {
        int recWidth = 1;
        int recHeight = 1;

        int[] buffer = new int[recWidth * recHeight];
        reader.getPixels(x, y, recWidth, recHeight, format, buffer, 0, recWidth);

        int alpha = 0;
        int red = 0;
        int green = 0;
        int blue = 0;

        for (int color : buffer) {
          alpha += (color >>> 24);
          red += (color >>> 16 & 0xFF);
          green += (color >>> 8 & 0xFF);
          blue += (color & 0xFF);
        }
        alpha = alpha / recWidth / recHeight;
        red = red / recWidth / recHeight;
        green = green / recWidth / recHeight;
        blue = blue / recWidth / recHeight;

        int color = (alpha << 24) + (red << 16) + (green << 8) + blue;
        Arrays.fill(buffer, color);

        writer.setPixels(x, y, recWidth, recHeight, format, buffer, 0, recWidth);
      }

    }
    System.out.println("Reader Type: " + reader.getPixelFormat().getType());
    System.out.println("Writer Type: " + writer.getPixelFormat().getType());

    try {
      BufferedImage bf = SwingFXUtils.fromFXImage(newimage, null);
      ImageIO.write(bf, "jpg", new File("C:\\temp\\test1.jpg"));
    } catch (IOException ex) {
      Logger.getLogger(WritableImageDemo.class.getName()).
              log(Level.SEVERE, null, ex);
    }
    try {
      Image img = new Image(new FileInputStream(new File("C:\\temp\\test1.jpg")));
      srcView3.setImage(img);
    } catch (IOException ex) {
      Logger.getLogger(WritableImageDemo.class.getName()).log(Level.SEVERE, null, ex);
    }
    return newimage;
  }

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

如果我运行此代码,我会得到这个结果。在左侧显示原始读取图像,在中间从方法复制,在右侧显示由SwingFXUtils.fromFXImage方法创建的图像。所以,这对我来说是一个错误!

If I run this code, I'll get this result. Showing in the left, the original read image, in middle the copied from the method and in the right the created one by the SwingFXUtils.fromFXImage method. So, this is to me a bug!

关于错误的新评论:


这可能与JIRA中的问题无关,但
以下是您程序中的错误:

It's probably not relevant to the problem in thie JIRA, but the following is a bug in your program:

srcView.snapshot(parameters, insert); 

您不能依赖实际使用传入图像的快照。它是
,如果可以,但为了正确,你需要使用方法的返回值
。例如:

You must not rely on snapshot actually using the passed in image. It will if it can, but for correctness you need to use the return value of the method. For example:

insert = srcView.snapshot(parameters, insert);


他们已安排版本9的错误修复。

and they have scheduled the bug fix for version 9.