java利用透明的圖片輪廓摳圖


需要處理的圖片:

1.png(空白區域為透明)

2.png

處理后的結果圖片:result.png

代碼如下:

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Transparency;
import java.awt.geom.Area;
import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.imageio.ImageIO;

/**
 * 
 * 利用透明的背景輪廓摳圖
 * 參考了:http://blog.csdn.net/daixinmei/article/details/51085575后實現
 *
 * @author yzl
 * @see [相關類/方法](可選)
 * @since [產品/模塊版本] (可選)
 */
public class TwoComposePic {

    /**
     * 
     * 將Image圖像中的透明/不透明部分轉換為Shape圖形
     *
     * @param img 圖片信息
     * @param transparent 是否透明
     * @return
     * @throws InterruptedException
     * @see [相關類/方法](可選)
     * @since [產品/模塊版本](可選)
     */
    public static Shape getImageShape(Image img, boolean transparent) throws InterruptedException {
        ArrayList<Integer> x = new ArrayList<Integer>();
        ArrayList<Integer> y = new ArrayList<Integer>();
        int width = img.getWidth(null);
        int height = img.getHeight(null);

        // 首先獲取圖像所有的像素信息
        PixelGrabber pgr = new PixelGrabber(img, 0, 0, -1, -1, true);
        pgr.grabPixels();
        int pixels[] = (int[]) pgr.getPixels();

        // 循環像素
        for (int i = 0; i < pixels.length; i++) {
            // 篩選,將不透明的像素的坐標加入到坐標ArrayList x和y中
            int alpha = (pixels[i] >> 24) & 0xff;
            if (alpha == 0) {
                continue;
            } else {
                x.add(i % width > 0 ? i % width - 1 : 0);
                y.add(i % width == 0 ? (i == 0 ? 0 : i / width - 1) : i / width);
            }
        }
        
        // 建立圖像矩陣並初始化(0為透明,1為不透明)
        int[][] matrix = new int[height][width];
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                matrix[i][j] = 0;
            }
        }

        // 導入坐標ArrayList中的不透明坐標信息
        for (int c = 0; c < x.size(); c++) {
            matrix[y.get(c)][x.get(c)] = 1;
        }

        /*
         * 逐一水平"掃描"圖像矩陣的每一行,將透明(這里也可以取不透明的)的像素生成為Rectangle,
         * 再將每一行的Rectangle通過Area類的rec對象進行合並, 最后形成一個完整的Shape圖形
         */
        Area rec = new Area();
        int temp = 0;
        //生成Shape時是1取透明區域還是取非透明區域的flag
        int flag = transparent ? 0 : 1; 

        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                if (matrix[i][j] == flag) {
                    if (temp == 0)
                        temp = j;
                    else if (j == width) {
                        if (temp == 0) {
                            Rectangle rectemp = new Rectangle(j, i, 1, 1);
                            rec.add(new Area(rectemp));
                        } else {
                            Rectangle rectemp = new Rectangle(temp, i, j - temp, 1);
                            rec.add(new Area(rectemp));
                            temp = 0;
                        }
                    }
                } else {
                    if (temp != 0) {
                        Rectangle rectemp = new Rectangle(temp, i, j - temp, 1);
                        rec.add(new Area(rectemp));
                        temp = 0;
                    }
                }
            }
            temp = 0;
        }
        return rec;
    }

    /**
     * 
     * 功能描述: <br>
     * 〈功能詳細描述〉
     *
     * @param back
     * @param head
     * @param out
     * @see [相關類/方法](可選)
     * @since [產品/模塊版本](可選)
     */
    public void composePic(String back, String head, String out) {
        try {
            //帶人物輪廓的背景圖(人物輪廓透明)
            File backFile = new File(back);
            Image backImg = ImageIO.read(backFile);
            int bw = backImg.getWidth(null);
            int bh = backImg.getHeight(null);

            //人物的head圖
            File headFile = new File(head);
            Image headImg = ImageIO.read(headFile);
            int lw = headImg.getWidth(null);
            int lh = headImg.getHeight(null);

            //得到透明的區域(人物輪廓)
            Shape shape = getImageShape(ImageIO.read(new File(back)), true);

            //合成后的圖片
            BufferedImage img = new BufferedImage(bw, bh, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = img.createGraphics();
            //設置畫布為透明
            img = g2d.getDeviceConfiguration().createCompatibleImage(bw, bh, Transparency.TRANSLUCENT);
            g2d.dispose();
            g2d = img.createGraphics();
            
            //取交集(限制可以畫的范圍為shape的范圍)
            g2d.clip(shape);
            
            //這里的坐標需要根據實際情況進行調整
            g2d.drawImage(headImg, 98, 10, lw, lh, null);
            
            g2d.dispose();

            ImageIO.write(img, "png", new File(out));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String args[]) throws IOException {
        String basePath = "E:/test/";
        TwoComposePic pic = new TwoComposePic();
        pic.composePic(basePath+"1.png", basePath+"2.png", basePath+"result.png");
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM