0

I painted some pixels in a Canvas node, like this:

canvas.getGraphicsContext2D().getPixelWriter().setColor(10, 10, Color.RED);

Then I scaled the canvas. Now the pixels are blury/smooth (see the first image). But what I'd like to achieve is depicted in the second image.

How can I do that?

Image 1 Image 2

Fabricio
  • 7,705
  • 9
  • 52
  • 87

2 Answers2

0

I looked through the GraphicsContext2D and Canvas API's and scoured the internet and SE but couldn't find anything that helped. In the end I settled for creating a canvas which was of the largest required size, then using canvas.setScaleX(a) and canvas.setScaleY(a) where 0<a<=1. That way you do get a scaling effect which does not blur the output in any way. Of course your "pixels" would be s by s in size where s is your maximum zoom factor. I guess the only downside is that it takes a factor s^2 more memory to store. Not ideal, but a work around I can cope with and use.

Not sure this will help anyone, but I recently found out that using java.awt.Graphics2D has the following commands, e.g.:

graphics.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_OFF);
graphics.setRenderingHint(KEY_DITHERING, VALUE_DITHER_DISABLE);
graphics.setRenderingHint(KEY_INTERPOLATION, VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
-1

Some ways of rendering images in javafx and indeed many of the components in javafx are anti-aliased meaning they will try to smooth, see here for another post covering it with images.

You could try drawing the pixels to an image view first and disabling the smoothing attribute and redrawing the image back onto the context:

ImageView scaledImageView = new ImageView(image);
scaledImageView.setSmooth(false);

However that would require a reimplementation of what you already have, and drawing the image back onto the context2d with the adjusted size.

This post here had the same issue with blurring caused by anti aliasing just for reference.

There are also some less invasive solutions that could work, sometimes anti aliasing can distort the image if you scale/zoom by a magnitude less than 2, examples 32x32, 64x64, it does this because:

At the device pixel level, integer coordinates map onto the corners and cracks between the pixels and the centers of the pixels appear at the midpoints between integer pixel locations. Because all coordinate values are specified with floating point numbers, coordinates can precisely point to these corners (when the floating point values have exact integer values) or to any location on the pixel. For example, a coordinate of (0.5, 0.5) would point to the center of the upper left pixel on the Stage. Similarly, a rectangle at (0, 0) with dimensions of 10 by 10 would span from the upper left corner of the upper left pixel on the Stage to the lower right corner of the 10th pixel on the 10th scanline. The pixel center of the last pixel inside that rectangle would be at the coordinates (9.5, 9.5).

Community
  • 1
  • 1
D3181
  • 2,037
  • 5
  • 19
  • 44