Объединение двух изображений

84

Мне нужно объединить два изображения (BufferedImage) в Java. Не было бы проблем, если бы не было прозрачности. Базовое изображение уже имеет некоторую прозрачность. Я хочу оставить это как есть и применить к нему «маску», второе изображение. Это второе изображение не имеет непрозрачных пикселей, на самом деле оно почти полностью прозрачно, только есть несколько менее прозрачных пикселей, которые создают своего рода «световой эффект», как рефлекс. Важная деталь: я не хочу делать это на экране с графикой, мне нужно получить BufferedImage с результирующим слиянием.

Может кто-нибудь мне помочь? Благодаря!

ДЕТАЛИ: объедините два изображения, сохраняя прозрачность. Вот что мне нужно сделать.

Примечание: эта альфа-маска Set BufferedImage в Java не выполняет то, что мне нужно, потому что она плохо справляется с двумя изображениями, имеющими прозрачность - она ​​изменяет прозрачность первого изображения.

Гильерме
источник

Ответы:

181

Просто создайте новое изображение BufferedImage с прозрачностью, а затем нарисуйте на нем два других изображения (с полной или полупрозрачностью). Вот как это будет выглядеть:

Изображение плюс оверлей

Пример кода (изображения называются image.png и 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"));
Питер Вальзер
источник
Есть ли способ разместить второе изображение в центре первого?
Ахмед
6
Разве вы не должны вызывать g.dispose (); в конце?
m-szalik
Привет, я последовал этому подходу и сохранил только второе изображение, но не первое изображение ... Любая помощь будет
принята с
@Peter Изображение становится серым, когда я направляю объединенный файл как файл jpeg. Пожалуйста, помогите
Мохаммед Шебин
3

Я не могу дать вам конкретного ответа, но java.awt.AlphaComposite - ваш друг. Вы получите полный контроль над тем, как вы хотите объединить два изображения. Однако это не так просто использовать - сначала вам нужно немного изучить теорию графики.

Стив Маклеод
источник
3

Не зная больше об эффекте, которого вы пытаетесь достичь, я просто укажу, что вы также можете рисовать прямо на BufferedImage. Таким образом, все, что вы можете сделать на экране, вы можете делать прямо на самом изображении.

Так что, если все, что вам нужно, это нарисовать одну поверх другой, это действительно просто. Просто возьмите объект Graphics для базового изображения и нарисуйте на нем другой.

Опять же, в зависимости от желаемого эффекта это может не сработать. Более подробная информация поможет лучше. Например, это задание для AlphaComposite, о котором упоминает другой респондент, или пользовательский ImageOp (или некоторая комбинация существующих ImageOps).

PSpeed
источник
1

объединить файлы любого типа по вертикали.

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);
        }
    }
Кумар Абхишек
источник