Об'єднання двох зображень


84

Мені потрібно об’єднати два зображення (BufferedImage) у Java. Це не було б проблемою, якби не було прозорості. Базове зображення вже має певну прозорість. Я хочу зберегти це як є і застосувати до нього "маску", друге зображення. Це друге зображення не має непрозорих пікселів, насправді воно майже повністю прозоре, просто має кілька менш прозорих пікселів, щоб надати якийсь «світловий ефект», як рефлекс. Важлива деталь: я не хочу робити це на екрані, з графікою, мені потрібно отримати BufferedImage з отриманим злиттям.

Хто-небудь може мені допомогти? Дякую!

ДЕТАЛІ: Об’єднайте два зображення, зберігаючи прозорість. Це те, що мені потрібно зробити.

Примітка: ця альфа-маска Set BufferedImage у Java не робить того, що мені потрібно, оскільки вона погано справляється з двома зображеннями, що мають прозорість - вона змінює прозорість першого зображення.

Відповіді:


179

Просто створіть новий 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

Привіт, я дотримувався цього підходу і зберігав лише друге зображення, але не перше зображення ... Будемо вдячні за будь-яку допомогу ...
TP_JAVA

@Peter Зображення стає сірим, коли я поправляю комбінований файл як файл JPEG. Будь ласка, допоможіть
Мохаммед Шебін

3

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


3

Не знаючи більше про ефект, якого ви намагаєтесь досягти, я лише зазначу, що ви також можете намалювати прямо на BufferedImage. Отже, все, що ви можете зробити на екрані, ви можете зробити прямо на самому зображенні.

Отже, якщо все, що вам потрібно, - це одне намальоване поверх іншого, це дійсно легко. Просто візьміть графічний об’єкт за базове зображення і намалюйте на ньому інший.

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


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);
        }
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.