The following are two PNG images:

Visually, they are absolutely identical - the only difference is that some pixels have a translucent background (you can download images to check this).
But when I use these images as the image cursor on JavaFX nodes, I get the following result:

The first cursor (without partially transparent pixels) is still crisp, but the second is distorted.
After working with the problem for a while, I found an algorithm that takes this difference into account - the mixing mode:
"Expected" mode (which you can see in the browser, for example) - is to take the sum of the values in the channel weighted by the alpha values: (1 - alpha) * background_color + alpha * foreground_color
.
" JavaFX" : (1 - alpha) * background_color + alpha^2 * foreground_color
( ).
, , , .
:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.scene.ImageCursor;
import javafx.scene.image.Image;
public class HelloWorld extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
System.out.println(ImageCursor.getBestSize(32, 32));
primaryStage.setTitle("Hello World!");
StackPane root = new StackPane();
root.setCursor(new ImageCursor(new Image("/test-cursor.png"), 0, 0));
primaryStage.setScene(new Scene(root, 100, 100));
primaryStage.show();
}
}
?