需要處理的圖片:
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"); } }