回敬Python蹭女神熱度助發朋友圈,Java實現頭像分成九宮圖,再生成拼圖頭像


前言:

晚上刷朋友圈,看到這樣一條朋友圈挺有意思的,如下:

 

 

於是,我點開文章后,大概看了下文章的意思,其實就是把一個圖片分成九宮圖,即拼圖的碎片,既然Python都能實現,作為回應,java也是可以做到的。

接着,一時技癢,整理了下思路。就馬上打開IDEA開始編碼,就有了這篇文章。

某號的實現:

將一張完整的圖片分割成9張小圖片,制作成朋友圈九宮格的圖片,從而在朋友圈曬出不一樣的美景。

我的追加實現:

將分割成的九個小圖片,在生成一個拼圖頭像圖片。

最終實現效果:

 

 

主要思路:

1、 一個待繪制的BufferedImage,長寬都是原圖的1/3

2、使用graphics,通過偏移量選擇繪制原圖的區域

3、繪制結束就可以輸出到文件

4、通過兩層循環,繪制9個位置的全部圖片

5、將生成九個拼圖碎片進行圖片合成

實現代碼:

1、生成拼圖碎片

具體示例代碼如下:

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;

/**
 * @author rongrong
 * @version 1.0
 * @description 將圖片分成九個拼圖碎片
 * @date 2020/7/28 20:20
 */
public class SetImage {
    public static void main(String[] args) {
        File imgfile;
        Image originimg;
        BufferedImage image;
        Graphics g;
        FileOutputStream out;
        JPEGImageEncoder encoder;
        try {
            // 獲取原始圖片
            imgfile = new File("D:\\picture\\original.jpg");
            originimg = ImageIO.read(imgfile);
            // 獲取原始圖片的寬和高
            int width = originimg.getWidth(null);
            int height = originimg.getHeight(null);
            // 如果輸入為長方形,重新計算長寬
            int outputwidth = width > height ? height : width;
            int outputheight = outputwidth;
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    // 九宮格,每張圖片大小都為原來的1/3
                    // 長方形,新建圖片大小為計算后的正方型的1/3
                    image = new BufferedImage(outputwidth / 3,
                            outputheight / 3, BufferedImage.TYPE_INT_RGB);
                    // 創建圖片
                    g = image.createGraphics();
                    // 繪制圖片
                    // 長方形,計算偏移量的數據采用計算后的正方形
                    g.drawImage(originimg, outputwidth * -i / 3, outputheight
                            * -j / 3, width, height, null);
                    // 圖片繪制完成,關閉g
                    g.dispose();
                    // 輸出流和輸出文件
                    out = new FileOutputStream("D:\\log\\" + (i+1)+ "-" + j + ".jpg");
                    // 下面代碼將輸出圖片轉換為JPEG、JPG文件
                    encoder = JPEGCodec.createJPEGEncoder(out);
                    encoder.encode(image);
                    out.close();
                    System.out.println("拼圖碎片已分拆成功");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

2、利用生成拼圖碎片合成頭像圖片

具體示例代碼如下:

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
 * @description 將九個拼圖生成頭像
 * @author rongrong
 * @version 1.0
 * @date 2020/7/28 21:18
 */
public class MakeGropHeadPic {
    /**圖片寬度*/
    private final Integer PIC_WIDTH = 422;
    /**圖片高度*/
    private final Integer PIC_HEIGHT = 422;
    /**空白寬度*/
    private final Integer PIC_SPACE = 14;

    /**小圖片寬度*/
    private Double LUMP_WIDTH = null;
    /**小圖片起始點橫坐標*/
    private Double LUMP_POINT_X = null;
    /**小圖片起始點縱坐標*/
    private Double LUMP_POINT_Y = null;


    // 圍邊使用的灰色
    private final int [] COLOR_GREY_BGR = new int[] {230, 230, 230};

    //校對數組使用下標
    private int flg = 0;

    public static void main(String[] args) {
        MakeGropHeadPic picUtil = new MakeGropHeadPic();
        //添加拼圖圖片
        List<String> pics = new ArrayList<>();
        pics.add("D:\\picture\\1-0.jpg");
        pics.add("D:\\picture\\2-0.jpg");
        pics.add("D:\\picture\\3-0.jpg");
        pics.add("D:\\picture\\1-1.jpg");
        pics.add("D:\\picture\\2-1.jpg");
        pics.add("D:\\picture\\3-1.jpg");
        pics.add("D:\\picture\\1-2.jpg");
        pics.add("D:\\picture\\2-2.jpg");
        pics.add("D:\\picture\\3-2.jpg");
        picUtil.getCombinationOfhead(pics,"D:\\picture\\","拼圖頭像");
    }

    /**
     * @param pics 圖片列表
     * @param path 存儲路徑
     * @param fileName 存儲圖片名稱
     * @return 成功 OR 失敗
     */
    public boolean getCombinationOfhead(List<String> pics, String path, String fileName){
        List<BufferedImage> bufferedImages = new ArrayList<BufferedImage>();

        // BufferedImage.TYPE_INT_RGB可以自己定義可查看API
        BufferedImage outImage = new BufferedImage(PIC_WIDTH, PIC_HEIGHT, BufferedImage.TYPE_INT_RGB);

        Graphics2D gra = outImage.createGraphics();
        //設置背景為藍灰色
        gra.setColor(toColor(COLOR_GREY_BGR));
        //填滿圖片
        gra.fillRect(0, 0, PIC_WIDTH, PIC_HEIGHT);

        // 開始拼湊 根據圖片的數量判斷該生成哪種樣式組合頭像

        Integer size = pics.size();//圖片數量
        Integer sqrt = (int)Math.ceil(Math.sqrt(size));//寬度  一行幾張圖片
        //計算出 單張圖片寬度
        LUMP_WIDTH = (PIC_WIDTH - ((sqrt + 1.0) * PIC_SPACE))/sqrt;

        System.out.println(LUMP_WIDTH);

        // 壓縮圖片所有的圖片生成尺寸同意的 為 125*125
        for (int i = 0; i < pics.size(); i++) {
            BufferedImage resize2 = resize2(pics.get(i), LUMP_WIDTH.intValue(), LUMP_WIDTH.intValue(), true);
            bufferedImages.add(resize2);
        }

        //缺幾個滿伍
        int lack = 0;
        //計算起始點坐標
        if(size < sqrt*(sqrt-1)){//少一行 不滿伍
            //缺幾個滿伍
            lack = sqrt*(sqrt-1) - size;
            //向右邊偏移量
            LUMP_POINT_X = PIC_SPACE.doubleValue() + lack * (LUMP_WIDTH + PIC_SPACE) / 2;
            //向下偏移量
            LUMP_POINT_Y = PIC_SPACE.doubleValue() + LUMP_WIDTH/2.;
         }else if (size == sqrt*(sqrt-1)){//滿伍少一行
            //向右邊偏移量
            LUMP_POINT_X = PIC_SPACE.doubleValue();
            //向下偏移量
            LUMP_POINT_Y = PIC_SPACE.doubleValue() + LUMP_WIDTH/2.;
         }else if(size < sqrt*sqrt){//不滿伍
            //缺幾個滿伍
            lack = sqrt*sqrt - size;
            //向右邊偏移量
            LUMP_POINT_X = PIC_SPACE.doubleValue()+ lack * (LUMP_WIDTH + PIC_SPACE) / 2;
            LUMP_POINT_Y = PIC_SPACE.doubleValue();
         }else if (size == sqrt*sqrt){//滿伍
            LUMP_POINT_X = PIC_SPACE.doubleValue();
            LUMP_POINT_Y = PIC_SPACE.doubleValue();
         }

        int line = lack==0?-1:0; //第幾行圖片
        int row = 0; //第幾列圖片
        for (int i = 0; i < bufferedImages.size(); i++){
            if ((i + lack) % sqrt == 0){
                line ++;
                row = 0;
            }
            if(line == 0){
                gra.drawImage(bufferedImages.get(i), LUMP_POINT_X.intValue() + (row++ * (PIC_SPACE+LUMP_WIDTH.intValue()))
                        , LUMP_POINT_Y.intValue(), null);
            }else{
                gra.drawImage(bufferedImages.get(i), PIC_SPACE + (row++ * (PIC_SPACE+LUMP_WIDTH.intValue()))
                        , LUMP_POINT_Y.intValue() + (line * (PIC_SPACE+LUMP_WIDTH.intValue())), null);
            }
        }

        File file = new File(path+fileName+".png");
        //文件如果存在先刪除,再創建
        try {
            if(!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
                if(file.exists()) {
                    file.delete();
                    if(!file.createNewFile()) {
                        System.out.println("創建失敗!");
                    }
                }
            }
        }catch(IOException e) {
            e.printStackTrace();
        }

        //將圖片寫到文件
        try {
            return ImageIO.write(outImage, "png", file);
        } catch (IOException e) {
            return false;
        }
    }


    /**
     * 圖片縮放
     * @param picPath 本地或網絡圖片路徑
     * @param height 縮放后高度
     * @param width 縮放后寬度
     * @param fill 是否填充灰色
     * @return BufferedImage
     */
    public BufferedImage resize2(String picPath, Integer height, Integer width, boolean fill){
        try {
            BufferedImage imageBuff =null;
            if(picPath.indexOf("https://")==0 || picPath.indexOf("http://")==0){ //簡單判斷是網絡圖片還是本地圖片
                imageBuff = ImageIO.read(new URL(picPath));
            }else{
                imageBuff = ImageIO.read(new File(picPath));
            }

            Image itemp = imageBuff.getScaledInstance(width, height, Image.SCALE_SMOOTH);

            double ratio = 0; // 縮放比例
            // 計算比例
            if ((imageBuff.getHeight() > height) || (imageBuff.getWidth() > width)) {
                if (imageBuff.getHeight() > imageBuff.getWidth()) {
                    ratio = height.doubleValue()/ imageBuff.getHeight();
                } else {
                    ratio = width.doubleValue() / imageBuff.getWidth();
                }
                AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);

                itemp = op.filter(imageBuff, null);
            }

            if (fill) {
                BufferedImage image = new BufferedImage(width, height,
                        BufferedImage.TYPE_INT_RGB);

                Graphics2D g = image.createGraphics();

                g.setColor(toColor(COLOR_GREY_BGR));

                g.fillRect(0, 0, width, height);

                if (width == itemp.getWidth(null))
                    g.drawImage(itemp, 0, (height - itemp.getHeight(null)) / 2,
                            itemp.getWidth(null), itemp.getHeight(null),
                            Color.white, null);
                else
                    g.drawImage(itemp, (width - itemp.getWidth(null)) / 2, 0,
                            itemp.getWidth(null), itemp.getHeight(null),
                            Color.white, null);
                g.dispose();
                itemp = image;
            }
            return (BufferedImage) itemp;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @toColor 顏色索引轉為顏色
     * @param colorRoot 顏色索引
     * @return 顏色
     */
    private Color toColor(int[] colorRoot) {
        if(colorRoot.length>=3) {
            return new Color(colorRoot[0], colorRoot[1], colorRoot[2]);
        }else {
            return null;
        }
    }
}

整個過程分為兩個部分:

1、轉換圖片、切割圖片和保存圖片

2、切割圖片合成新圖片

體驗:

最后,我們找一張圖片來做測試,比如我把源文件放到D盤的picture文件夾下,如下圖:

 

 

1、首先,運行先生成拼圖圖片,即九宮格的碎片。結果如下圖所示:

 

 從截圖我們可以看到,我們的圖片切割精准都是正方形,所以這段代碼拿去盡管去用即可。

 

 

2、將九張拼圖合成一個圖片頭像,在來運行第二個類,結果如下圖所示:

 

最后

以上便是一個生成拼圖碎片,再生成拼圖頭像的過程。感興趣的朋友,還不趕緊去試試?

大家如果覺得喜歡,點個“在看”並分享給更多的朋友吧!


免責聲明!

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



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