Comment rogner une image en Java?

Je veux recadrer une image manuellement à l’aide de la souris.
Supposons que l’image contienne du texte et que je souhaite sélectionner du texte à partir d’une image, pour cela, je souhaite rogner cette zone à l’aide de la souris.

La solution que j’ai trouvée la plus utile pour rogner une image en mémoire tampon utilise la méthode getSubImage (x, y, w, h);

Ma routine de culture a fini par ressembler à ceci:

private BufferedImage cropImage(BufferedImage src, Rectangle rect) { BufferedImage dest = src.getSubimage(0, 0, rect.width, rect.height); return dest; } 

La réponse principale à cette question pose deux problèmes majeurs potentiels. Tout d’abord, selon les documents:

public BufferedImage getSubimage (int x, int y, int w, int h)

Renvoie une sous-image définie par une région rectangular spécifiée. Le BufferedImage retourné partage le même tableau de données que l’image d’origine.

Essentiellement, cela signifie que le résultat de getSubimage agit comme un pointeur qui pointe vers une sous-section de l’image d’origine.

Pourquoi est-ce important? Eh bien, si vous envisagez d’éditer la sous-image pour quelque raison que ce soit, les modifications seront également apscopes à l’image d’origine. Par exemple, j’ai rencontré ce problème lorsque j’utilisais la plus petite image dans une fenêtre séparée pour zoomer sur l’image d’origine. (un peu comme une loupe). J’ai permis d’inverser les couleurs pour voir certains détails plus facilement, mais la zone “zoomée” s’est également inversée dans l’image d’origine! Donc, il y avait une petite section de l’image originale qui avait inversé les couleurs alors que le rest était normal. Dans de nombreux cas, cela n’aura aucune importance, mais si vous souhaitez modifier l’image, ou si vous voulez simplement une copie de la section rognée, vous pouvez envisager une méthode.

Ce qui nous amène au deuxième problème. Heureusement, le problème n’est pas aussi important que le premier. getSubImage partage le même tableau de données que l’image d’origine. Cela signifie que la totalité de l’image d’origine est toujours stockée en mémoire. En supposant que “rogner” l’image que vous voulez réellement une image plus petite, vous devrez la redessiner comme une nouvelle image plutôt que de simplement obtenir la sous-image.

Essaye ça:

 BufferedImage img = image.getSubimage(startX, startY, endX, endY); //fill in the corners of the desired crop location here BufferedImage copyOfImage = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB); Graphics g = copyOfImage.createGraphics(); g.drawImage(img, 0, 0, null); return copyOfImage; //or use it however you want 

Cette technique vous donnera l’image recadrée que vous recherchez, sans le lien vers l’image d’origine. Cela préservera l’intégrité de l’image d’origine et vous évitera de devoir stocker la plus grande image. (Si vous vider l’image originale plus tard)

C’est une méthode qui fonctionnera:

 import java.awt.image.BufferedImage; import java.awt.Rectangle; import java.awt.Color; import java.awt.Graphics; public BufferedImage crop(BufferedImage src, Rectangle rect) { BufferedImage dest = new BufferedImage(rect.getWidth(), rect.getHeight(), BufferedImage.TYPE_ARGB_PRE); Graphics g = dest.getGraphics(); g.drawImage(src, 0, 0, rect.getWidth(), rect.getHeight(), rect.getX(), rect.getY(), rect.getX() + rect.getWidth(), rect.getY() + rect.getHeight(), null); g.dispose(); return dest; } 

Bien sûr, vous devez créer votre propre JComponent:

 import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.image.BufferedImage; import java.awt.Rectangle; import java.awt.Graphics; import javax.swing.JComponent; public class JImageCropComponent extends JComponent implements MouseListener, MouseMotionListener { private BufferedImage img; private int x1, y1, x2, y2; public JImageCropComponent(BufferedImage img) { this.img = img; this.addMouseListener(this); this.addMouseMotionListener(this); } public void setImage(BufferedImage img) { this.img = img; } public BufferedImage getImage() { return this; } @Override public void paintComponent(Graphics g) { g.drawImage(img, 0, 0, this); if (cropping) { // Paint the area we are going to crop. g.setColor(Color.RED); g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.max(x1, x2), Math.max(y1, y2)); } } @Override public void mousePressed(MouseEvent evt) { this.x1 = evt.getX(); this.y1 = evt.getY(); } @Override public void mouseReleased(MouseEvent evt) { this.cropping = false; // Now we crop the image; // This is the method a wrote in the other snipped BufferedImage cropped = crop(new Rectangle(Math.min(x1, x2), Math.min(y1, y2), Math.max(x1, x2), Math.max(y1, y2)); // Now you have the cropped image; // You have to choose what you want to do with it this.img = cropped; } @Override public void mouseDragged(MouseEvent evt) { cropping = true; this.x2 = evt.getX(); this.y2 = evt.getY(); } //TODO: Implement the other unused methods from Mouse(Motion)Listener } 

Je ne l’ai pas testé. Peut-être y a-t-il des erreurs (je ne suis pas sûr de toutes les importations).

Vous pouvez mettre la méthode de crop(img, rect) dans cette classe. J’espère que cela t’aides.

 File fileToWrite = new File(filePath, "url"); BufferedImage bufferedImage = cropImage(fileToWrite, x, y, w, h); private BufferedImage cropImage(File filePath, int x, int y, int w, int h){ try { BufferedImage originalImgage = ImageIO.read(filePath); BufferedImage subImgage = originalImgage.getSubimage(x, y, w, h); return subImgage; } catch (IOException e) { e.printStackTrace(); return null; } } 

Cette question n’a pas assez d’informations pour répondre. Une solution générale (en fonction de votre infrastructure graphique): ajoutez un gestionnaire d’événement de souris qui interceptera les clics et les mouvements de la souris. Cela vous donnera vos coordonnées (x, y). Utilisez ensuite ces coordonnées pour recadrer votre image.

Vous devez en savoir plus sur l’API Java Image et l’API liée à la souris, peut-être quelque part dans le java.awt.event package .

Pour commencer, vous devez pouvoir charger et afficher l’image à l’écran, vous utiliserez peut-être un JPanel .

Ensuite, à partir de là, vous allez essayer d’implémenter une interface de programme de détection de mouvements de la souris et d’autres interfaces associées. Peut-être que vous serez lié à la méthode mouseDragged

Pour une action mousedragged , vous obtenez la coordonnée de la forme rectangle par le glisser …

Ensuite, à partir de ces coordonnées, vous obtiendrez la sous-image de l’image que vous avez et vous pourrez en quelque sorte la redessiner ….

Et ensuite afficher l’image recadrée … Je ne sais pas si ça va marcher, juste un produit de mon imagination … juste une pensée!

Je donne cet exemple parce que cela fonctionne réellement pour mon cas d’utilisation.

Pour la méthode ci-dessous, la BoundingBox est la sous-image que vous essayez de recadrer.

 private BufferedImage cropImage(BufferedImage image, BoundingBox box) { Rectangle goal = new Rectangle(Math.round(box.getLeft()* image.getWidth()),Math.round(box.getTop()* image.getHeight()),Math.round(box.getWidth() * image.getWidth()), Math.round(box.getHeight() * image.getHeight())); Rectangle clip = goal.intersection(new Rectangle(image.getWidth(), image.getHeight())); BufferedImage clippedImg = image.getSubimage(clip.x, clip.y , clip.width, clip.height); return clippedImg; }