Question

I ai essayé d'utiliser la méthode drawOval avec la même hauteur et largeur, mais que le diamètre augmente le cercle devient pire à la recherche. Que puis-je faire pour avoir un cercle décent, peu importe d'aspect de la taille. Comment puis-je mettre en œuvre l'anti-aliasing en Java ou une autre méthode.

Était-ce utile?

La solution

Il se trouve que, Java2D (qui je suppose est ce que vous utilisez) est déjà très bon à cela! Il y a un tutoriel décent ici: http: //www.javaworld .com / JavaWorld / jw-08-1998 / jw-08-media.html

La ligne est importante:

graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                          RenderingHints.VALUE_ANTIALIAS_ON);

Autres conseils

vous pouvez définir le rendu des notes:

Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
    RenderingHints.VALUE_ANTIALIAS_ON);

Deux choses qui peuvent aider:

  1. Utilisez Graphics2D.draw(Shape) avec une instance de java.awt.geom.Ellipse2D au lieu de Graphics.drawOval
  2. Si le résultat est toujours pas satisfaisante, essayez d'utiliser Graphics2D.setRenderingHint pour activer l'antialiasing

Exemple

public void paint(Graphics g) {
    Graphics2D g2d = (Graphics2D) g;
    Shape theCircle = new Ellipse2D.Double(centerX - radius, centerY - radius, 2.0 * radius, 2.0 * radius);
    g2d.draw(theCircle);
}

Voir la réponse de Josef pour un exemple de setRenderingHint

Bien sûr, vous définissez votre rayon à ce que jamais vous avez besoin:

@Override
public void paint(Graphics g) {
    Graphics2D g2d = (Graphics2D) g;
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    Ellipse2D.Double hole = new Ellipse2D.Double();
    hole.width = 28;
    hole.height = 28;
    hole.x = 14;
    hole.y = 14;
    g2d.draw(hole);
}

Merci à Oleg Estekhin pour remarquer le rapport de bogue, car il explique comment le faire.

Voici quelques petits cercles avant et après. Grossie plusieurs fois pour voir la grille de pixels.

Les cercles avant et après

En descendant une rangée, ils se déplacent légèrement par des quantités de sous-pixels.

La première colonne est sans rendre des notes. Le second est avec anticrénelage seulement. Le troisième est le mode d'anticrénelage et pure.

Notez comment avec anticrénelage conseils seulement, les trois premiers cercles sont les mêmes, et les deux derniers sont également les mêmes. Il semble y avoir une transition discrète qui se passe. arrondi probablement à un moment donné.

Voici le code. Il est en Jython pour une meilleure lisibilité, mais il entraîne la bibliothèque d'exécution Java sous et peut être sans perte de source équivalente portage Java, avec exactement le même effet.

from java.lang import *
from java.io import *
from java.awt import *
from java.awt.geom import *
from java.awt.image import *
from javax.imageio import *

bim = BufferedImage(30, 42, BufferedImage.TYPE_INT_ARGB)
g = bim.createGraphics()
g.fillRect(0, 0, 100, 100)
g.setColor(Color.BLACK)
for i in range(5):
    g.draw(Ellipse2D.Double(2+0.2*i, 2+8.2*i, 5, 5))

g.setRenderingHint( RenderingHints.  KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON)

for i in range(5):
    g.draw(Ellipse2D.Double(12+0.2*i, 2+8.2*i, 5, 5))

g.setRenderingHint( RenderingHints.  KEY_STROKE_CONTROL,
                    RenderingHints.VALUE_STROKE_PURE)

for i in range(5):
    g.draw(Ellipse2D.Double(22+0.2*i, 2+8.2*i, 5, 5))

#You'll probably want this too later on:
#g.setRenderingHint( RenderingHints.  KEY_INTERPOLATION,
#                    RenderingHints.VALUE_INTERPOLATION_BICUBIC)
#g.setRenderingHint( RenderingHints.  KEY_RENDERING, 
#                    RenderingHints.VALUE_RENDER_QUALITY)

ImageIO.write(bim, "PNG", File("test.png"))

Résumé: vous avez besoin à la fois VALUE_ANTIALIAS_ON et VALUE_STROKE_PURE pour obtenir une bonne regardant des cercles dessinés avec une précision de sous-pixel

.

Incapacité pour dessiner un « cercle d'apparence décent » est lié au très vieux bug 6431487 .

Mise antialiasing ne contribue pas beaucoup - il suffit de vérifier le genre de « cercle » produit par le drawOval () ou drawShape (Eclipse) lorsque la taille du cercle requis est de 16 pixels (encore assez commun pour la taille des icônes) et anticrénelage est sur. Plus grands cercles anticrénelage sera mieux, mais ils sont toujours asymétriques, si quelqu'un prendra soin de les regarder de près.

Il semble que de dessiner un « cercle d'apparence décente » on doit dessiner manuellement un. Sans anticrénelage il sera algorithme de cercle médian (cette question a une réponse avec un joli code java pour elle).

ÉDITÉ: 06 Septembre 2017

C'est un algorithme inventé par moi pour dessiner un cercle sur une matrice entière. La même idée pourrait être utilisé pour écrire un cercle à l'intérieur d'un BufferedImage. Si vous essayez de dessiner ce cercle en utilisant les graphiques de classe ce n'est pas Answare que vous recherchez (sauf si vous souhaitez modifier chaque couleur assignement avec g.drawLine (x, y, x + 1, y), mais il pourrait être très lent).

protected boolean runOnCircumference(int[][] matrix, int x, int y, int ray, int color) {
    boolean ret;
    int[] rowUpper = null, rowInferior = null, rowCenterUpper = null, rowCenterInferior = null;

    if (ret = ray > 0) {
        if (ray == 1) {
            matrix[y][x + 1] = color;
            rowUpper = matrix[++y];
            rowUpper[x] = color;
            rowUpper[x + 2] = color;
            matrix[y][x] = color;
        } else {
            double rRay = ray + 0.5;
            int r = 0, c = 0, ray2 = ray << 1, ray_1 = ray - 1, halfRay = (ray >> 1) + ray % 2, rInf,
                    ray1 = ray + 1, horizontalSymmetricOldC;
            // draw cardinal points

            rowUpper = matrix[ray + y];
            rowUpper[x] = color;
            rowUpper[x + ray2] = color;
            matrix[y][x + ray] = color;
            matrix[ray2 + y][x + ray] = color;

            horizontalSymmetricOldC = ray1;
            rInf = ray2;
            c = ray_1;
            for (r = 0; r < halfRay; r++, rInf--) {

                rowUpper = matrix[r + y];
                rowInferior = matrix[rInf + y];

                while (c > 0 && (Math.hypot(ray - c, (ray - r)) < rRay)) {

                    rowUpper[x + c] = color;
                    rowUpper[x + horizontalSymmetricOldC] = color;
                    rowInferior[x + c] = color;
                    rowInferior[x + horizontalSymmetricOldC] = color;

                    // get the row pointer to optimize
                    rowCenterUpper = matrix[c + y];
                    rowCenterInferior = matrix[horizontalSymmetricOldC + y];
                    // draw
                    rowCenterUpper[x + r] = color;
                    rowCenterUpper[x + rInf] = color;
                    rowCenterInferior[x + r] = color;
                    rowCenterInferior[x + rInf] = color;
                    horizontalSymmetricOldC++;
                    c--;
                }
            } // end r circle
        }
    }
    return ret;
}

Je l'ai essayé tant de fois, vérifier manuellement exactitude, donc je pense que cela va fonctionner. Je ne l'ai pas fait de gamme chèque juste pour simplifier le code. J'espère que cela vous aidera et tout le monde souhaite dessiner un cercle sur une matrice (par exemple, les programmeurs qui tente de créer leurs propres jeux vidéos sur le code pur et la nécessité de gérer une orientée matrice jeu carte pour stocker les objets se trouvant sur le jeu-map [si vous avez besoin d'aide à ce sujet, écrivez-moi]).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top