J'ai ce programme:Java Graphics.fillXxx() en combinaison avec Graphics2D.scale()
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class TestLine {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new TestLine().start();
}
});
}
private static void start() {
JFrame frame = new JFrame();
frame.setContentPane(new CarthPanel());
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private static class CarthPanel extends JComponent {
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D gg = (Graphics2D) g;
int w = gg.getClipBounds().width;
int h = gg.getClipBounds().height;
System.out.println("(w,h)=(" + w + "," + h + ")");
gg.translate(w - 1, 0); // <<< when uncommenting both lines, mirroring applies
gg.scale(-1.0, 1.0); //
paintTest(gg, w, h);
}
private static void paintTest(Graphics2D g, int w, int h) {
// black background
g.setColor(Color.black);
g.fillRect(0, 0, w, h);
// colored corners
g.setColor(Color.RED);
g.drawLine(0, 0, 10, 0);
g.drawLine(0, 0, 0, 10);
g.setColor(Color.RED);
g.drawLine(0, 199, 10, 199);
g.drawLine(0, 199, 0, 189);
g.setColor(Color.CYAN);
g.drawLine(189, 0, 199, 0);
g.drawLine(199, 0, 199, 10);
g.setColor(Color.CYAN);
g.drawLine(189, 199, 199, 199);
g.drawLine(199, 199, 199, 189);
// yellow squares
g.setColor(Color.yellow);
g.drawRect(3, 3, 10, 10);
g.fillRect(186, 3, 11, 11);
g.fillRect(3, 186, 11, 11);
g.drawRect(186, 186, 10, 10);
String chars = "ABC";
g.setFont(Font.decode("Arial 72"));
Rectangle2D rect = g.getFontMetrics().getStringBounds(chars, g);
g.drawString(chars, (int) (200 - rect.getWidth())/2, (int) (200 - rect.getHeight()));
}
}
}
Si vous exécutez ce programme une fois avec deux lignes particulières et commentées puis une fois avec les mêmes lignes en commentaire (voir le code), vous pouvez voir ceci:
[
Si vous ne l'avez pas repérer le problème, voici une photo zoomée:
On s'attendrait à ce que l'image soit parfaitement reflétée. Ceci est vrai pour tous les traits et formes creuses (= méthodes drawXxx()). Cependant, toutes les formes remplies (= méthodes fillXxx()) sont dessinées exactement à un pixel à gauche de l'endroit où je les attend; par exemple. les rectangles jaunes remplis, et vous pouvez également remarquer que le fond noir s'est décalé, comme vu par la ligne blanche à la frontière droite.
Est-ce un bug ou est-ce prévu? Je soupçonne qu'il a quelque chose à voir avec la différence comment « largeur » et « hauteur » sont en cours de traitement dans des procédés drawXxx() et fillXxx():
- résultats drawRect (x, y, w, h) dans un rectangle creux avec des limites d'axe X x et x + w, de sorte que le rectangle est w + 1 pixels de large. FillRect (x, y, w, h) donne un rectangle rempli avec les limites x et x + w-1 de l'axe X, de sorte que le rectangle a une largeur de w pixels.
Que manque-t-il?
Que voulez-vous dire par "tous les drawXXX sont faux"? De mes tests c'est clairement les formes remplies qui sont décalées, pas les formes décrites. Vous avez raison: le contexte graphique de BufferedImage fonctionne! Cela doit donc être un bug dans le contexte graphique du composant Java. – Timmos
Je pense que votre exemple est presque correct, 'g.drawImage (img, 0, 0, null);' devrait être 'gg.drawImage (img, 0, 0, null);'. – Timmos
Je suppose que votre réponse n'est pas correcte après tout.Chaque fois que vous prenez un contexte graphique à partir d'un BufferedImage et que vous le redimensionnez/traduisez, les méthodes fillXxx() entraînent également des décalages de pixels. Dans votre exemple, vous avez tout dessiné directement sur le BufferedImage (sans aucune transformation), puis vous avez mis à l'échelle/traduit tout le contenu en une seule fois lorsque vous dessinez l'image sur l'objet graphique Java Component. Cela fonctionne en effet, mais votre hypothèse selon laquelle cela est lié au contexte graphique lui-même est fausse: le bogue est là chaque fois que vous dessinez sur un contexte mis à l'échelle/traduit - drawXxx() est pixelisé. – Timmos