การรวมภาพสองภาพ


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"));

มีวิธีที่จะให้ภาพที่สองอยู่ตรงกลางภาพแรกหรือไม่?
Ahmed

6
คุณไม่ควรเรียกใช้ g.dispose (); ในตอนท้าย?
m-szalik

สวัสดีฉันทำตามวิธีนี้และบันทึกเฉพาะภาพที่สอง แต่ไม่ใช่ภาพแรก ... ขอความช่วยเหลือใด ๆ ที่นี่ ..
TP_JAVA

@Peter รูปภาพจะเป็นสีเทาเมื่อฉันแก้ไขไฟล์ที่รวมเป็นไฟล์ jpeg โปรดช่วย
Mohammed shebin

3

ฉันไม่สามารถให้คำตอบที่เฉพาะเจาะจงกับคุณได้ แต่ java.awtAlphaComposite นี่คือเพื่อนของคุณ คุณจะได้รับการควบคุมอย่างสมบูรณ์ว่าคุณต้องการให้ทั้งสองภาพผสานกันอย่างไร อย่างไรก็ตามมันไม่ได้ใช้ตรงไปตรงมาคุณต้องเรียนรู้ทฤษฎีกราฟิกก่อน


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);
        }
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.