8

I'm developing an application which needs a lot of comparing image data in JavaFX. For that comparing, I need to to get rgb data of pixels in the images. Let's say that the picture I need to compare is Picture1 and Picture2. Picture1 is an input picture selected by the user. Picture2 is a drawing that I make programmatically.

AFAIK, the only way to get rgb data per pixel in JavaFX is with PixelReader of Image. It's fine for the Picture1 since it's an input. But I need to do a drawing on Picture2 and Picture2 is a Canvas (I draw polygons on Picture2 and because drawing pixel by pixel with PixelWriter is a bit complicated IMO) and doesn't have a PixelReader or something with similar functionality. So my solution is as follows:

  1. Read input image and make Picture1
  2. Make a Canvas and do the drawing
  3. Attach the Canvas to a Scene
  4. Make snapshot of the Scene and make WritableImage (Picture2)
  5. Compare Picture1 and Picture2

So I have a method with something like:

public static WritableImage makeDrawableImage(Canvas in) {
     AnchorPane root = new AnchorPane(in);
     WritableImage out = new WritableImage((int)in.getWidth(), (int)in.getHeight());
     Scene sc = new Scene(root, in.getWidth(), in.getHeight());

     out = in.snapshot(null, null);

     return out;
}

However it takes a really long time for the snapshot to finish. The value of out never gets assigned. I don't know what I did wrong.

Is there any alternative to convert Canvas to Image or WritableImage? Or maybe there is a library to do drawing of polygons easier with PixelWriter?

Please be soft on me. This is my first question on Stack Overflow and I'm not a real programmer nor an IT student. I code as a hobby.

So, thanks in advance. Cheers.

Jonny Henly
  • 4,023
  • 4
  • 26
  • 43

1 Answers1

2

You can create a snapshot of a canvas with this method:

public static WritableImage pixelScaleAwareCanvasSnapshot(Canvas canvas, double pixelScale) {
    WritableImage writableImage = new WritableImage((int)Math.rint(pixelScale*canvas.getWidth()), (int)Math.rint(pixelScale*canvas.getHeight()));
    SnapshotParameters spa = new SnapshotParameters();
    spa.setTransform(Transform.scale(pixelScale, pixelScale));
    return canvas.snapshot(spa, writableImage);     
}

The pixel scale normally is 1.0 unless you have a HiDPI screen.

mipa
  • 10,369
  • 2
  • 16
  • 35
  • It still doesn't work :( My problem is with the 'out = in.snapshot(null, null);' It takes really long time. Is it really take that long to make a snapshot? – Teguh Hidayat Apr 25 '16 at 09:16
  • What doen't work for you? How large are your images? – mipa Apr 25 '16 at 09:19
  • Obviously you are still using your code and not mine. In my code there is no line 'out = in.snapshot(null, null);' Taking a snapshot of a 2000x2000 canvas just takes milliseconds. – mipa Apr 25 '16 at 09:25
  • `return canvas.snapshot(spa, writableImage)` doesn't give anything. I think it's because it takes a long time.Is that right?. The canvas is 600x1000. Thanks anyway – Teguh Hidayat Apr 25 '16 at 09:28
  • If it takes so long for you, then this is suspicious. Maybe you have drawn so much into the canvas, that the rendering has not yet finished? – mipa Apr 25 '16 at 09:45
  • I found the problem with my code. I just realized that the method was ran on another thread so the `snapshot` doesn't work. Anyway thanks mipa :) – Teguh Hidayat Apr 25 '16 at 11:35