77 votes

Comment recadrer 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 veuille sélectionner du texte dans une image, alors pour cela, je veux recadrer cette zone en utilisant la souris.

0 votes

Plusieurs bonnes idées ci-dessous. Voir aussi java.sun.com/docs/books/tutorial/2d

0 votes

Hussain : donnez à l'une de ces réponses détaillées le contrôle

163voto

codehead Points 611

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

Ma routine de recadrage a fini par ressembler à ceci :

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

63 votes

Pourquoi ne pas inclure également les coordonnées x et y. BufferedImage dest = src.getSubimage(rect.x, rect.y, rect.width, rect.height);

0 votes

Merci, Codehead et Sorter !

47voto

Il y a deux problèmes potentiellement majeurs avec la réponse principale à cette question. Premièrement, selon la documentation :

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

Renvoie une sous-image définie par une région rectangulaire spécifiée. La BufferedImage renvoyée partage le même tableau de données que l'image originale. originale.

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

Pourquoi est-ce important ? Eh bien, si vous envisagez de modifier la sous-image pour une raison quelconque, les modifications seront également apportées à l'image originale. Par exemple, j'ai rencontré ce problème lorsque j'ai utilisé la plus petite image dans une fenêtre séparée pour zoomer sur l'image originale. (un peu comme une loupe). J'ai rendu possible l'inversion des couleurs pour voir certains détails plus facilement, mais la zone qui était "zoomée" était également inversée dans l'image originale ! Il y avait donc une petite section de l'image originale qui avait des couleurs inversées alors que le reste de l'image restait normal. Dans de nombreux cas, cela n'aura pas d'importance, mais si vous voulez modifier l'image, ou si vous voulez simplement une copie de la section recadrée, vous pouvez envisager une méthode.

Ce qui nous amène au deuxième problème. Heureusement, ce n'est pas un problème aussi important que le premier. getSubImage partage le même tableau de données que l'image originale. Cela signifie que l'intégralité de l'image originale est toujours stockée en mémoire. En supposant qu'en "recadrant" l'image, vous voulez en fait une image plus petite, vous devrez la redessiner comme une nouvelle image plutôt que de simplement obtenir la sous-image.

Essayez ç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 lien vers l'image originale. Cela permet de préserver l'intégrité de l'image originale et d'économiser la mémoire nécessaire au stockage d'une image plus grande. (Si vous supprimez l'image originale plus tard).

1 votes

Vous auriez pu simplement utiliser la fonction clone() de la classe Object.

16voto

Martijn Courteaux Points 33836

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 entendu, 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 le crop(img, rect) dans cette classe. J'espère que cela vous aidera.

2 votes

Merci de m'avoir répondu mais cela donne beaucoup d'erreurs ! pouvez-vous me donner un code simple pour recadrer une image ?

6voto

Maurits Rijk Points 4873

Cette question ne comporte pas suffisamment d'informations pour y répondre. Une solution générale (qui dépend de votre cadre d'interface graphique) : ajoutez un gestionnaire d'événement de souris qui captera 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.

2voto

ultrajohn Points 1196

Vous devez vous renseigner sur l'API Java Image et l'API liée à la souris, peut-être quelque part sous la rubrique java.awt.event package .

Pour commencer, vous devez être en mesure de charger et d'afficher l'image à l'écran, peut-être utiliserez-vous un fichier de type JPanel .

Ensuite, à partir de là, vous allez essayer d'implémenter une interface d'écoute des mouvements de la souris et d'autres interfaces connexes. Vous serez peut-être lié à la mouseDragged méthode...

Pour un mousedragged vous obtiendrez les coordonnées du rectangle formé par le déplacement...

Ensuite, à partir de ces coordonnées, vous obtiendrez la sous-image de l'image que vous avez et vous la redessinerez en quelque sorte à nouveau.....

Et ensuite afficher l'image recadrée... Je ne sais pas si cela va fonctionner, c'est juste le fruit de mon imagination... juste une idée !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X