¿Cómo puedo crear un pincel con efecto de plumaje en JavaFX?
Entonces estoy tratando de crear un programa de editor de fotos muy básico en Java, usando JavaFX. Hasta ahora logré hacer funcionar un pincel y una goma de borrar de la siguiente manera:
package application;
import java.io.File;
import javax.imageio.ImageIO;
import javafx.application.Platform;
import javafx.embed.swing.SwingFXUtils;
import javafx.fxml.FXML;
import javafx.geometry.Point2D;
import javafx.scene.canvas.*;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
public class EditorController {
private boolean eraser = false;
@FXML
private Canvas canvas;
@FXML
private ColorPicker colorPicker;
@FXML
private TextField brushSize;
@FXML
private TextField selectedTool;
private Point2D last = null;
public void initialize() {
GraphicsContext gc = canvas.getGraphicsContext2D();
canvas.setOnMouseReleased(e -> {last = null;});
canvas.setOnMouseClicked(e -> {
if (!eraser) {
double size = Double.parseDouble(brushSize.getText());
float mouseX = (float) e.getX();
float mouseY = (float) e.getY();
gc.fillOval(mouseX-(size/2), mouseY-(size/2), size, size);
}
});
canvas.setOnMouseDragged(e -> {
System.out.println(eraser);
double size = Double.parseDouble(brushSize.getText());
gc.setLineCap(StrokeLineCap.ROUND);
gc.setLineWidth(size);
float mouseX = (float) e.getX();
float mouseY = (float) e.getY();
if (last != null && !eraser) {
gc.strokeLine(last.getX(), last.getY(), mouseX, mouseY);
} else if (eraser) {
gc.clearRect(mouseX, mouseY, size, size);
}
last = new Point2D(mouseX, mouseY);
});
}
public void onSave() {
try {
Image snapshot = canvas.snapshot(null, null);
ImageIO.write(SwingFXUtils.fromFXImage(snapshot, null), "png", new File("paint.png"));
} catch (Exception e) {
System.out.println("Failed to save image: " + e);
}
}
public void onLoad() {
// not implemented yet
}
// not implemented yet
public void onUndo() { }
public void onRedo() { }
public void onSmaller() { }
public void onBigger() { }
public void onResetView() { }
public void onFitView() { }
public void onFillView() { }
public void onNewLayer() { }
public void onDeleteLayer() { }
public void onDuplicateLayer() { }
public void onGroupLayers() { }
public void onMergeLayers() { }
public void onAddMask() { }
public void onBrush() { eraser = false; selectedTool.setText("Brush"); }
public void onEraser() { eraser = true; selectedTool.setText("Eraser"); }
public void onExit() {
Platform.exit();
}
}
Ahora quiero tener un valor de suavidad / dureza para el pincel (como en photoshop) donde pueda dibujar una línea de aspecto más suave, pero no estoy seguro de cómo lograrlo con JavaFX. ¿Hay herramientas dentro de ella para cosas como esta?
Entonces, con un ejemplo visual: el pincel a la izquierda sería un pincel suavizado, el de la derecha no lo es (y eso es lo que tengo actualmente)
davy.ai
Para lograr un valor de suavidad/dureza para el pincel en JavaFX, se puede modificar el método
gc.setLineWidth()
en el métodocanvas.setOnMouseDragged()
. En lugar de establecer un valor fijo para el ancho de línea, se puede calcular en función de la distancia entre la posición actual del ratón y la posición anterior del ratón. Cuanto mayor sea la distancia, más suave será la línea. Aquí hay un ejemplo de implementación:En este ejemplo, la variable
distance
se calcula como la distancia euclidiana entre la posición del ratón anterior (last
) y la posición actual del ratón (e.getX()
ye.getY()
). Esta distancia se utiliza para calcular un valor delineWidth
, que es un porcentaje del valor desize
(tamaño del pincel). Cuanto mayor sea ladistancia
, más pequeño será el valor delineWidth
, lo que dará como resultado una línea más suave.Se puede ajustar el valor
50
para cambiar la sensibilidad del suavizado de línea. Un valor más bajo dará como resultado una línea más suave con menos distancia, mientras que un valor más alto dará como resultado una línea más dura con más distancia.Con esta modificación, se debería poder lograr un resultado similar al del pincel suavizado en la imagen de ejemplo.