Reducteur d'image

Description

Cette source fournit une interface pour redimentionner une ou plusieurs images. On peut choisir un ou plusieurs fichiers grace à un JFileChooser ou bien en ajouter d'autres par drag and drop de fichier.
Pour supprimer un ou plusieurs fichiers de la liste, selectonner et appuyer sur "suppr".
J'ai essayé de tout mettre dans un seul fichier :-)

La source utilise entre autre :
- SwingWorker pour mettre à jour une barre de progression et effectuer un traitement long en rafraichissant régulièrement l'IHM.
- Redimmmensionnement d'image
- Le Drop sur une JList
- Utilisation d'un JFileChooser pour choix de fichiers multiples ou de repertoire

Source / Exemple :


package com.hwoarang.image_scaler;

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.DefaultListModel;
import javax.swing.DropMode;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingWorker;
import javax.swing.TransferHandler;
import javax.swing.filechooser.FileFilter;

public class CimageScaler extends JPanel
{
   private static final long     serialVersionUID           = 1L;

   private final static String   TEXT_EXPLICATION           = "Cliquer sur le bouton 'Ajouter' pour selectionner"
                                                                  + " les images a convertir puis"
                                                                  + " appuyer sur 'Convertir'."
                                                                  + " Pour supprimer une ou plusieurs images,"
                                                                  + " les selectionner et appuyer sur"
                                                                  + " la touche 'suppr'. Vous pouvez également"
                                                                  + " faire du drag and drop des fichiers à analyser";

   private final static String   TEXT_DEF_LAB_EN_COURS      = "Pas de fichier en cours";

   private final static String   FEN_TITRE                  = "Image reducteur";

   private final static String   VAL_PREFIX_INI             = "rd_";
   private final static String   VAL_WIDTH_MAX_INI          = "500";
   private final static String   VAL_HEIGHT_MAX_INI         = "500";
   private final static String   VAL_REP_DEST_INI           = "";

   private final static String   TEXT_INFORMATION           = "Information";
   private final static String   TEXT_ERREUR                = "Erreur";
   private final static String   TEXT_FINI_OK               = "Conversion terminee";
   private final static String   TEXT_FINI_KO               = "Erreur lors de la conversion";
   private final static String   TEXT_LARGEUR_MAX           = "Largeur max";
   private final static String   TEXT_HAUTEUR_MAX           = "Hauteur max";
   private final static String   TEXT_PREFIX                = "Prefix";
   private final static String   TEXT_RERTOIRE_DEST         = "Repertoire destination";
   private final static String   TEXT_BOU_CHOIX_REP         = "...";
   private final static String   TEXT_BOU_AJOUTER           = "Ajouter";
   private final static String   TEXT_BOU_GO                = "Convertir";
   private final static String   TEXT_TITRE_REP_DESTINATION = "Repertoire de destination";
   private final static String   TEXT_TITRE_TYPE_IMAGES     = "Images";

   private final static String[] EXT_VALID                  = ImageIO
                                                                  .getReaderFileSuffixes();

   public static final Insets    NO_INSETS                  = new Insets(0, 0,
                                                                  0, 0);

   private JList                 listImgs;
   private DefaultListModel      listImgsModel;
   private JTextField            tfRepDest;
   private JTextField            tfWidthMax;
   private JTextField            tfHeightMax;
   private JTextField            tfPrefix;
   private JButton               bouAjout;
   private JButton               bouGo;
   private JLabel                labEnCours;
   private JProgressBar          pbProgress;

   public static void main(String[] args)
   {
      JFrame f = new JFrame(FEN_TITRE);
      CimageScaler m = new CimageScaler();
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      f.getContentPane().add(m);
      f.pack();

      f.setVisible(true);
   }

   public CimageScaler()
   {
      this.setLayout(new GridBagLayout());
      this.setPreferredSize(new Dimension(500, 500));

      GridBagConstraints c = new GridBagConstraints();
      final int nbColonnesMax = 3;
      int ligne = 0;
      final JLabel labW = new JLabel(TEXT_LARGEUR_MAX);
      c.fill = GridBagConstraints.BOTH;
      c.gridx = 0;
      c.gridy = ligne;
      c.gridwidth = 1;
      c.gridheight = 1;
      c.weightx = 0;
      c.weighty = 0;
      this.add(labW, c);

      tfWidthMax = new JTextField(VAL_WIDTH_MAX_INI);
      c.fill = GridBagConstraints.BOTH;
      c.gridx = 1;
      c.gridy = ligne;
      c.gridwidth = nbColonnesMax - 1;
      c.gridheight = 1;
      c.weightx = 1;
      c.weighty = 0;
      this.add(tfWidthMax, c);
      ligne++;

      final JLabel labHauteurMax = new JLabel(TEXT_HAUTEUR_MAX);
      c.fill = GridBagConstraints.BOTH;
      c.gridx = 0;
      c.gridy = ligne;
      c.gridwidth = 1;
      c.gridheight = 1;
      c.weightx = 0;
      c.weighty = 0;
      this.add(labHauteurMax, c);

      tfHeightMax = new JTextField(VAL_HEIGHT_MAX_INI);
      c.fill = GridBagConstraints.BOTH;
      c.gridx = 1;
      c.gridy = ligne;
      c.gridwidth = nbColonnesMax - 1;
      c.gridheight = 1;
      c.weightx = 1;
      c.weighty = 0;
      this.add(tfHeightMax, c);
      ligne++;

      final JLabel labPrefix = new JLabel(TEXT_PREFIX);
      c.fill = GridBagConstraints.BOTH;
      c.gridx = 0;
      c.gridy = ligne;
      c.gridwidth = 1;
      c.gridheight = 1;
      c.weightx = 0;
      c.weighty = 0;
      this.add(labPrefix, c);

      tfPrefix = new JTextField(VAL_PREFIX_INI);
      c.fill = GridBagConstraints.BOTH;
      c.gridx = 1;
      c.gridy = ligne;
      c.gridwidth = nbColonnesMax - 1;
      c.gridheight = 1;
      c.weightx = 1;
      c.weighty = 0;
      this.add(tfPrefix, c);
      ligne++;

      final JLabel labRepDest = new JLabel(TEXT_RERTOIRE_DEST);
      c.fill = GridBagConstraints.BOTH;
      c.gridx = 0;
      c.gridy = ligne;
      c.gridwidth = 1;
      c.gridheight = 1;
      c.weightx = 0;
      c.weighty = 0;
      this.add(labRepDest, c);

      tfRepDest = new JTextField(VAL_REP_DEST_INI);
      c.fill = GridBagConstraints.BOTH;
      c.gridx = 1;
      c.gridy = ligne;
      c.gridwidth = 1;
      c.gridheight = 1;
      c.weightx = 1;
      c.weighty = 0;
      this.add(tfRepDest, c);

      final JButton bouChoixRep = new JButton(TEXT_BOU_CHOIX_REP);
      bouChoixRep.setMargin(NO_INSETS);
      c.fill = GridBagConstraints.BOTH;
      c.gridx = 2;
      c.gridy = ligne;
      c.gridwidth = 1;
      c.gridheight = 1;
      c.weightx = 0;
      c.weighty = 0;
      this.add(bouChoixRep, c);
      ligne++;

      final JTextArea taExplication = new JTextArea(TEXT_EXPLICATION);
      taExplication.setBackground(this.getBackground());
      taExplication.setLineWrap(true);
      taExplication.setWrapStyleWord(true);
      taExplication.setEditable(false);
      c.fill = GridBagConstraints.HORIZONTAL;
      c.gridx = 0;
      c.gridy = ligne;
      c.gridwidth = 1;
      c.gridheight = 1;
      c.weightx = 0;
      c.weighty = 1;
      this.add(taExplication, c);

      listImgsModel = new DefaultListModel()
      {
         private static final long serialVersionUID = 1L;

         @Override
         public void addElement(Object o)
         {
            // On n'accepte que les fichiers
            if ((o != null) && (o instanceof File))
            {
               File f = (File) o;
               // Si le repertoire de destination n'est pas rempli, on le
               // prerempli avec le chemin de la premiere image
               if ("".equals(tfRepDest.getText()))
               {
                  String path = f.getParent() + File.separator;
                  tfRepDest.setText(path);
               }
               super.addElement(f);
            }
         }
      };
      listImgs = new JList(listImgsModel);
      listImgs.setDropMode(DropMode.INSERT);
      c.fill = GridBagConstraints.BOTH;
      c.gridx = 1;
      c.gridy = ligne;
      c.gridwidth = nbColonnesMax - 1;
      c.gridheight = 3;
      c.weightx = 1;
      c.weighty = 1;
      JScrollPane sp = new JScrollPane(listImgs);
      this.add(sp, c);
      ligne++;

      bouAjout = new JButton(TEXT_BOU_AJOUTER);
      c.fill = GridBagConstraints.BOTH;
      c.gridx = 0;
      c.gridy = ligne;
      c.gridwidth = 1;
      c.gridheight = 1;
      c.weightx = 0;
      c.weighty = 0;
      this.add(bouAjout, c);
      ligne++;

      bouGo = new JButton(TEXT_BOU_GO);
      c.fill = GridBagConstraints.BOTH;
      c.gridx = 0;
      c.gridy = ligne;
      c.gridwidth = 1;
      c.gridheight = 1;
      c.weightx = 0;
      c.weighty = 0;
      this.add(bouGo, c);
      ligne++;

      labEnCours = new JLabel(TEXT_DEF_LAB_EN_COURS);
      labEnCours.setHorizontalAlignment(JLabel.HORIZONTAL);
      c.fill = GridBagConstraints.BOTH;
      c.gridx = 0;
      c.gridy = ligne;
      c.gridwidth = nbColonnesMax;
      c.gridheight = 1;
      c.weightx = 1;
      c.weighty = 0;
      this.add(labEnCours, c);
      ligne++;

      pbProgress = new JProgressBar(JProgressBar.HORIZONTAL, 100);
      pbProgress.setStringPainted(true);
      c.fill = GridBagConstraints.BOTH;
      c.gridx = 0;
      c.gridy = ligne;
      c.gridwidth = nbColonnesMax;
      c.gridheight = 1;
      c.weightx = 1;
      c.weighty = 0;
      this.add(pbProgress, c);
      ligne++;

      listImgs.addKeyListener(new KeyAdapter()
      {
         public void keyPressed(KeyEvent e)
         {
            keyPressedOnListImg(e);
         }
      });

      bouAjout.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent ae)
         {
            actionPerformedAddButton(ae);
         }
      });

      bouChoixRep.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent ae)
         {
            actionPerformedBouChoixRep(ae);
         }
      });

      bouGo.addActionListener(new ActionListener()
      {
         public void actionPerformed(ActionEvent ae)
         {
            actionPerformedBouGo(ae);
         }
      });

      TransferHandler th = new TransferHandler()
      {
         private static final long serialVersionUID = 1L;

         @Override
         public boolean canImport(JComponent comp, DataFlavor[] transferFlavors)
         {
            boolean ret = false;
            int i = 0;
            // On n'accepte que les fichiers
            while ((i < transferFlavors.length)
                  && (DataFlavor.javaFileListFlavor.equals(transferFlavors[i]) == false))
            {
               i++;
            }

            if (i < transferFlavors.length)
            {
               ret = true;
            }
            return ret;
         }

         @SuppressWarnings("unchecked")
         @Override
         public boolean importData(JComponent comp, Transferable t)
         {
            boolean ret = false;

            try
            {
               List<File> listFiles = (List<File>) t
                     .getTransferData(DataFlavor.javaFileListFlavor);
               for (File f : listFiles)
               {
                  // On verifie si c'est bien une image
                  if (isFileOk(f) != false)
                  {
                     listImgsModel.addElement(f);
                  }
               }
            }
            catch (Exception ex)
            {
               ex.printStackTrace();
            }

            return ret;
         }
      };
      listImgs.setTransferHandler(th);
   }

   private void actionPerformedAddButton(ActionEvent ae)
   {
      File[] sf = getFiles();
      if (sf != null)
      {
         for (File f : sf)
         {
            String fileExt = getFileExtension(f);
            if ((fileExt != null) && (isStringInList(fileExt, EXT_VALID)))
            {
               listImgsModel.addElement(f);
            }
         }
      }
   }

   private void actionPerformedBouChoixRep(ActionEvent ae)
   {
      JFileChooser fc = new JFileChooser();
      fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
      fc.addChoosableFileFilter(new FileFilter()
      {
         public boolean accept(File f)
         {
            boolean ret = f.isDirectory();
            return ret;
         }

         public String getDescription()
         {
            return TEXT_TITRE_REP_DESTINATION;
         }

      });
      int returnVal = fc.showOpenDialog(null);
      if (returnVal == JFileChooser.APPROVE_OPTION)
      {
         File f = fc.getSelectedFile();
         String rep = f.getAbsolutePath();
         if (rep.endsWith(File.separator) == false)
         {
            rep = rep + File.separator;
         }
         tfRepDest.setText(rep);
      }
   }

   private void actionPerformedBouGo(ActionEvent ae)
   {
      try
      {
         bouAjout.setEnabled(false);
         bouGo.setEnabled(false);
         final File[] sf = new File[listImgsModel.getSize()];
         for (int i = 0; i < sf.length; i++)
         {
            sf[i] = (File) listImgsModel.get(i);
         }
         final int w = Integer.parseInt(tfWidthMax.getText());
         final int h = Integer.parseInt(tfHeightMax.getText());
         final String pre = tfPrefix.getText();
         String path = tfRepDest.getText();
         if (path.endsWith(File.separator) == false)
         {
            path = path + File.separator;
         }
         final String pathFinal = path;
         SwingWorker<Void, String> sw = new SwingWorker<Void, String>()
         {
            @Override
            protected Void doInBackground() throws Exception
            {
               try
               {
                  File rep = new File(pathFinal);
                  // On cree le repertoire s'il n'existe pas
                  if (rep.exists() == false)
                  {
                     rep.mkdir();
                  }
                  String[] lfwfn = ImageIO.getWriterFormatNames();
                  for (int i = 0; i < sf.length; i++)
                  {
                     File f = sf[i];
                     String fileExt = getFileExtension(f);
                     if (isStringInList(fileExt, lfwfn))
                     {
                        System.out.println("Opening : " + f.getAbsolutePath());
                        // Pour mettre a jour le label qui affiche le nom
                        // de fichiers
                        this.publish(f.getAbsolutePath());
                        BufferedImage imgOri = ImageIO.read(f);
                        BufferedImage dest = scale(imgOri, w, h);
                        String newFileName = pathFinal + pre + f.getName();
                        ImageIO.write(dest, fileExt, new File(newFileName));
                        pbProgress.setValue((i + 1) * 100 / sf.length);
                     }
                     else
                     {
                        System.err.println("Unknown file format : "
                              + f.getAbsolutePath());
                     }
                  }
               }
               catch (Exception ex)
               {
                  ex.printStackTrace();
               }
               return null;
            }

            @Override
            protected void process(List<String> chunks)
            {
               for (String s : chunks)
               {
                  labEnCours.setText(s);
               }

            }

            @Override
            protected void done()
            {
               bouAjout.setEnabled(true);
               bouGo.setEnabled(true);
               labEnCours.setText(TEXT_DEF_LAB_EN_COURS);
               pbProgress.setValue(0);
               JOptionPane.showMessageDialog(null, TEXT_FINI_OK,
                     TEXT_INFORMATION, JOptionPane.INFORMATION_MESSAGE);
            }
         };
         sw.execute();
      }
      catch (Exception ex)
      {
         ex.printStackTrace();
         bouAjout.setEnabled(true);
         bouGo.setEnabled(true);
         labEnCours.setText(TEXT_DEF_LAB_EN_COURS);
         pbProgress.setValue(0);
         JOptionPane.showMessageDialog(null, TEXT_FINI_KO, TEXT_ERREUR,
               JOptionPane.ERROR_MESSAGE);
      }

   }

   private void keyPressedOnListImg(KeyEvent e)
   {
      switch (e.getKeyCode())
      {
         case KeyEvent.VK_DELETE:
         {
            int[] index = listImgs.getSelectedIndices();
            if (index != null)
            {
               // On supprime les fichiers selectionnes de la liste. Pour
               // eviter de tout decaler, on supprime d'abord les index
               // les plus eleves
               for (int i = index.length; i > 0; i--)
               {
                  listImgsModel.remove(index[i - 1]);
               }
            }
            break;
         }

         default:
         {
            break;
         }
      }
   }

   private String getFileExtension(File f)
   {
      String ret = f.getName();

      int index = ret.lastIndexOf('.');
      if ((index >= 0) && ((index + 1) < ret.length()))
      {
         ret = ret.substring(index + 1).toLowerCase();
      }
      else
      {
         ret = null;
      }
      return ret;
   }

   private boolean isStringInList(String fileExt, String[] list)
   {
      boolean ret = false;
      int i = 0;
      while ((i < list.length) && (ret == false))
      {
         ret = list[i].equals(fileExt);
         i++;
      }

      return ret;
   }

   private File[] getFiles()
   {
      File[] ret = null;
      JFileChooser fc = new JFileChooser();
      fc.setMultiSelectionEnabled(true);
      fc.addChoosableFileFilter(new FileFilter()
      {
         public boolean accept(File f)
         {
            boolean ret = f.isDirectory();
            if (ret == false)
            {
               ret = isFileOk(f);
            }
            return ret;
         }

         public String getDescription()
         {
            return TEXT_TITRE_TYPE_IMAGES;
         }

      });
      int returnVal = fc.showOpenDialog(null);
      if (returnVal == JFileChooser.APPROVE_OPTION)
      {
         ret = fc.getSelectedFiles();
      }
      return ret;
   }

   private boolean isFileOk(File f)
   {
      int i = 0;
      boolean ret = false;
      String nomFichier = f.getName().toLowerCase();
      while ((ret == false) && (i < EXT_VALID.length))
      {
         ret = nomFichier.endsWith("." + EXT_VALID[i]);
         i++;
      }
      return ret;
   }

   private static BufferedImage scale(BufferedImage srcImg, int width,
         int height)
   {
      double rapW;
      double rapH;
      double rap;
      rapW = (double) srcImg.getWidth(null) / (double) width;
      rapH = (double) srcImg.getHeight(null) / (double) height;
      if (rapW > rapH)
      {
         rap = rapW;
      }
      else
      {
         rap = rapH;
      }

      int typeImg;
      if (BufferedImage.TYPE_CUSTOM == srcImg.getType())
      {
         typeImg = BufferedImage.TYPE_INT_ARGB;
      }
      else
      {
         typeImg = srcImg.getType();
      }

      double w = (double) srcImg.getWidth(null) / rap;
      double h = (double) srcImg.getHeight(null) / rap;
      /* On cree une nouvelle image a la bonne taille */
      BufferedImage newImg = new BufferedImage((int) w, (int) h, typeImg);

      // On recopie l'image
      Graphics2D g = newImg.createGraphics();
      g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
            RenderingHints.VALUE_INTERPOLATION_BILINEAR);
      g.drawImage(srcImg, 0, 0, (int) w, (int) h, null);
      g.dispose();

      return newImg;
   }
}

Conclusion :


J'espère que cette source va plaire. N'hesitez pas à laisser un commentaire

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.