90 votes

Fusionner deux images

Je dois fusionner deux images (BufferedImage) en Java. Ce ne serait pas un problème s'il n'y avait pas de transparence. L'image de base a déjà une certaine transparence. Je veux la garder telle quelle et lui appliquer un "masque", la deuxième image. Cette deuxième image n'a pas de pixels opaques, en fait elle est presque complètement transparente, elle a juste quelques pixels moins transparents pour donner une sorte "d'effet de lumière", comme un reflex. Détail important : Je ne veux pas faire cela à l'écran, avec des graphiques, j'ai besoin d'obtenir une BufferedImage avec la fusion résultante.

Quelqu'un peut-il m'aider ? Merci !

DÉTAILS : Fusionner deux images en maintenant la transparence. Voici ce que je dois faire.

Remarque : cette Définir le masque alpha de BufferedImage en Java ne fait pas ce dont j'ai besoin car il ne gère pas bien les deux images ayant une transparence - il modifie la transparence de la première image.

204voto

Peter Walser Points 5112

Il suffit de créer une nouvelle BufferedImage avec transparence, puis de peindre les deux autres images (avec transparence totale ou semi-transparence) sur celle-ci. Voici à quoi cela ressemblera :

Image plus overlay

Exemple de code (les images sont appelées 'image.png' et 'overlay.png') :

File path = ... // base path of the images

// load source images
BufferedImage image = ImageIO.read(new File(path, "image.png"));
BufferedImage overlay = ImageIO.read(new File(path, "overlay.png"));

// create the new image, canvas size is the max. of both image sizes
int w = Math.max(image.getWidth(), overlay.getWidth());
int h = Math.max(image.getHeight(), overlay.getHeight());
BufferedImage combined = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);

// paint both images, preserving the alpha channels
Graphics g = combined.getGraphics();
g.drawImage(image, 0, 0, null);
g.drawImage(overlay, 0, 0, null);

g.dispose();

// Save as new image
ImageIO.write(combined, "PNG", new File(path, "combined.png"));

0 votes

Y a-t-il un moyen d'avoir la deuxième image au centre de la première ?

7 votes

Ne devriez-vous pas invoquer g.dispose() ; à la fin ?

0 votes

Bonjour, j'ai suivi cette approche et j'ai sauvegardé seulement la deuxième image mais pas la première... Toute aide ici serait appréciée....

4voto

Kumar Abhishek Points 1248

Fusionner verticalement tout type de fichier.

void mergeFiles(List<String> files, String fileName) {
        int heightTotal = 0;
        int maxWidth = 100;

        List<BufferedImage> images = new ArrayList<>();
        try {
            for (String file : files) {
                BufferedImage image = ImageIO.read(new File(file));
                images.add(image);
            }

        for (BufferedImage bufferedImage : images) {
            heightTotal += bufferedImage.getHeight();
            if (bufferedImage.getWidth() > maxWidth) {
                maxWidth = bufferedImage.getWidth();
            }
        }

        int heightCurr = 0;
        BufferedImage concatImage = new BufferedImage(maxWidth, heightTotal, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = concatImage.createGraphics();
        for (BufferedImage bufferedImage : images) {
            g2d.drawImage(bufferedImage, 0, heightCurr, null);
            heightCurr += bufferedImage.getHeight();
        }

        File compressedImageFile = new File(fileName);
        OutputStream outputStream = new FileOutputStream(compressedImageFile);

        float imageQuality = 0.7f;
        Iterator<ImageWriter> imageWriters = ImageIO.getImageWritersByFormatName("jpeg");

        if (!imageWriters.hasNext())
            throw new IllegalStateException("Writers Not Found!!");

        ImageWriter imageWriter = imageWriters.next();
        ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(outputStream);
        imageWriter.setOutput(imageOutputStream);

        ImageWriteParam imageWriteParam = imageWriter.getDefaultWriteParam();

        //Set the compress quality metrics
        imageWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        imageWriteParam.setCompressionQuality(imageQuality);

        //Created image
        imageWriter.write(null, new IIOImage(concatImage, null, null), imageWriteParam);

        // close all streams
        outputStream.close();
        imageOutputStream.close();
        imageWriter.dispose();
        log.info(" Files Merged");
        } catch (IOException e) {
            log.error("Error while merging files :::"+e);
            throw new RuntimeException(e);
        }
    }

4voto

Steve McLeod Points 19016

Je ne peux pas vous donner une réponse précise, mais java.awt.AlphaComposite est votre ami. Vous aurez un contrôle absolu sur la façon dont vous voulez que les deux images fusionnent. Cependant, il n'est pas simple à utiliser - vous devez d'abord apprendre un peu de théorie graphique.

4voto

PSpeed Points 2388

Sans en savoir plus sur l'effet que vous cherchez à obtenir, je vous signale que vous pouvez également dessiner directement sur une BufferedImage. Ainsi, tout ce que vous pouvez faire à l'écran, vous pouvez le faire directement sur l'image elle-même.

Donc, si tout ce que vous voulez, c'est que l'un soit dessiné au-dessus de l'autre, c'est très facile. Il suffit de prendre l'objet graphique de l'image de base et d'y dessiner l'autre.

Encore une fois, selon l'effet exact que vous recherchez, cela peut ne pas fonctionner. Plus de détails permettraient de mieux vous aider. Par exemple, s'agit-il d'un travail pour AlphaComposite comme le mentionne l'autre répondant ou d'une ImageOp personnalisée (ou une combinaison d'ImageOps existantes).

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