loytime

关于Java实现图片的叠加与拼接的文档网络上确实很多,碰巧小编开发工作中也遇到这些问题,就做了简要的梳理,分享给大家,以期能够互相学习。

Java对图片的处理主要使用的是BufferedImage类。

BufferedImage 子类描述具有可访问图像数据缓冲区的 ImageBufferedImage 由图像数据的 ColorModelRaster 组成。RasterSampleModel 中 band 的数量和类型必须与 ColorModel 所要求的数量和类型相匹配,以表示其颜色和 alpha 分量。所有 BufferedImage 对象的左上角坐标都为 (0, 0)。因此,用来构造 BufferedImage 的任何 Raster 都必须满足:minX=0 且 minY=0。此类依靠 Raster 的数据获取方法、数据设置方法,以及 ColorModel 的颜色特征化方法。 

以上主要来源于官方文档,我们来时直接写实践代码吧。

首先将文件转化为BufferedImage对象,这里给出两种读取文件并转化为BufferedImage对象的方法。点击+查看隐藏代码。

 1  /**
 2      * @param fileUrl
 3      *            文件绝对路径或相对路径
 4      * @return 读取到的缓存图像
 5      * @throws IOException
 6      *             路径错误或者不存在该文件时抛出IO异常
 7      */
 8     public static BufferedImage getBufferedImage(String fileUrl)
 9             throws IOException {
10         File f = new File(fileUrl);
11         return ImageIO.read(f);
12     }
13     
14     
15     /**
16      * 远程图片转BufferedImage
17      * @param destUrl    远程图片地址
18      * @return
19      */
20     public static BufferedImage getBufferedImageDestUrl(String destUrl) {
21         HttpURLConnection conn = null;
22         BufferedImage image = null;
23         try {
24             URL url = new URL(destUrl);
25             conn = (HttpURLConnection) url.openConnection();
26             if (conn.getResponseCode() == 200) {
27                 image = ImageIO.read(conn.getInputStream());
28                 return image;
29             }
30         } catch (Exception e) {
31             e.printStackTrace();
32         } finally {
33             conn.disconnect();
34         }
35         return image;
36     }
37     
View Code

接下来是将BufferedImage对象保存到本地,具体方法如下

 1 /**
 2      * 输出拼接叠加图片
 3      * 
 4      * @param buffImg
 5      *            图像拼接叠加之后的BufferedImage对象
 6      * @param savePath
 7      *            图像拼接叠加之后的保存路径
 8      */
 9     public static void generateSaveFile(BufferedImage buffImg, String savePath) {
10         int temp = savePath.lastIndexOf(".") + 1;
11         try {
12             File outFile = new File(savePath);
13             if(!outFile.exists()){
14                 outFile.createNewFile();
15             }
16             ImageIO.write(buffImg, savePath.substring(temp), outFile);
17             System.out.println("ImageIO write...");
18         } catch (IOException e) {
19             e.printStackTrace();
20         }
21     }

上面作为准备部分,现在开始图片叠加的实现方法:

 1  /**
 2      * 
 3      * @Title: 构造图片
 4      * @Description: 生成水印并返回java.awt.image.BufferedImage
 5      * @param buffImg
 6      *            源文件(BufferedImage)
 7      * @param waterFile
 8      *            水印文件(BufferedImage)
 9      * @param x
10      *            距离右下角的X偏移量
11      * @param y
12      *            距离右下角的Y偏移量
13      * @param alpha
14      *            透明度, 选择值从0.0~1.0: 完全透明~完全不透明
15      * @return BufferedImage
16      * @throws IOException
17      */
18     public static BufferedImage overlyingImage(BufferedImage buffImg, BufferedImage waterImg, int x, int y, float alpha) throws IOException {
19 
20         // 创建Graphics2D对象,用在底图对象上绘图
21         Graphics2D g2d = buffImg.createGraphics();
22         int waterImgWidth = waterImg.getWidth();// 获取层图的宽度
23         int waterImgHeight = waterImg.getHeight();// 获取层图的高度
24         // 在图形和图像中实现混合和透明效果
25         g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
26         // 绘制
27         g2d.drawImage(waterImg, x, y, waterImgWidth, waterImgHeight, null);
28         g2d.dispose();// 释放图形上下文使用的系统资源
29         return buffImg;
30     }
31     
View Code

图片拼接的实现方法:

 /**
     * 待合并的两张图必须满足这样的前提,如果水平方向合并,则高度必须相等;如果是垂直方向合并,宽度必须相等。
     * mergeImage方法不做判断,自己判断。
     *
     * @param img1
     *            待合并的第一张图
     * @param img2
     *            带合并的第二张图
     * @param isHorizontal
     *            为true时表示水平方向合并,为false时表示垂直方向合并
     * @return 返回合并后的BufferedImage对象
     * @throws IOException
     */
    public static BufferedImage mergeImage(BufferedImage img1,
            BufferedImage img2, boolean isHorizontal) throws IOException {
        int w1 = img1.getWidth();
        int h1 = img1.getHeight();
        int w2 = img2.getWidth();
        int h2 = img2.getHeight();

        // 从图片中读取RGB
        int[] ImageArrayOne = new int[w1 * h1];
        ImageArrayOne = img1.getRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 逐行扫描图像中各个像素的RGB到数组中
        int[] ImageArrayTwo = new int[w2 * h2];
        ImageArrayTwo = img2.getRGB(0, 0, w2, h2, ImageArrayTwo, 0, w2);

        // 生成新图片
        BufferedImage DestImage = null;
        if (isHorizontal) { // 水平方向合并
            DestImage = new BufferedImage(w1+w2, h1, BufferedImage.TYPE_INT_RGB);
            DestImage.setRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 设置上半部分或左半部分的RGB
            DestImage.setRGB(w1, 0, w2, h2, ImageArrayTwo, 0, w2);
        } else { // 垂直方向合并
            DestImage = new BufferedImage(w1, h1 + h2, BufferedImage.TYPE_INT_RGB);
            DestImage.setRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 设置上半部分或左半部分的RGB
            DestImage.setRGB(0, h1, w2, h2, ImageArrayTwo, 0, w2); // 设置下半部分的RGB
        }

        return DestImage;
    }
View Code

测试方法如下:

 1 /**
 2      * Java 测试图片叠加方法
 3      */
 4     public static void overlyingImageTest() {
 5 
 6         String sourceFilePath = "D://test//test1.jpg";
 7         String waterFilePath = "D://test//test2.jpg";
 8         String saveFilePath = "D://test//overlyingImageNew.jpg";
 9         try {
10             BufferedImage bufferImage1 = getBufferedImage(sourceFilePath);
11             BufferedImage bufferImage2 = getBufferedImage(waterFilePath);
12 
13             // 构建叠加层
14             BufferedImage buffImg = overlyingImage(bufferImage1, bufferImage2, 0, 0, 1.0f);
15             // 输出水印图片
16             generateSaveFile(buffImg, saveFilePath);
17         } catch (IOException e) {
18             e.printStackTrace();
19         }
20 
21     }
22     
23     /**
24      * Java 测试图片合并方法
25      */
26     public static void imageMargeTest() {
27         // 读取待合并的文件
28         BufferedImage bi1 = null;
29         BufferedImage bi2 = null;
30         // 调用mergeImage方法获得合并后的图像
31         BufferedImage destImg = null;
32         System.out.println("下面是垂直合并的情况:");
33         String saveFilePath = "D://test//new1.jpg";
34         String divingPath = "D://test//new2.jpg";
35         String margeImagePath = "D://test//margeNew.jpg";
36         try {
37             bi1 = getBufferedImage(saveFilePath);
38             bi2 = getBufferedImage(divingPath);
39             // 调用mergeImage方法获得合并后的图像
40             destImg = mergeImage(bi1, bi2, false);
41         } catch (IOException e) {
42             e.printStackTrace();
43         }
44         // 保存图像
45         generateSaveFile(destImg, margeImagePath);
46         System.out.println("垂直合并完毕!");
47     }
48 
49     public static void main(String[] args) {
50         // 测试图片的叠加
51         overlyingImageTest();
52         // 测试图片的垂直合并
53         imageMargeTest();
54     }
View Code

全部代码整体如下:

package ImagePackage;

import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.imageio.ImageIO;

/**

 * 该类实现了图片的合并功能,可以选择水平合并或者垂直合并。
 * 当然此例只是针对两个图片的合并,如果想要实现多个图片的合并,只需要自己实现方法 BufferedImage
 * mergeImage(BufferedImage[] imgs, boolean isHorizontal)即可;
 * 而且这个方法更加具有通用性,但是时间原因不实现了,方法和两张图片实现是一样的
 */

public class ImageMerge {

    /**
     * @param fileUrl
     *            文件绝对路径或相对路径
     * @return 读取到的缓存图像
     * @throws IOException
     *             路径错误或者不存在该文件时抛出IO异常
     */
    public static BufferedImage getBufferedImage(String fileUrl)
            throws IOException {
        File f = new File(fileUrl);
        return ImageIO.read(f);
    }
    
    
    /**
     * 远程图片转BufferedImage
     * @param destUrl    远程图片地址
     * @return
     */
    public static BufferedImage getBufferedImageDestUrl(String destUrl) {
        HttpURLConnection conn = null;
        BufferedImage image = null;
        try {
            URL url = new URL(destUrl);
            conn = (HttpURLConnection) url.openConnection();
            if (conn.getResponseCode() == 200) {
                image = ImageIO.read(conn.getInputStream());
                return image;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            conn.disconnect();
        }
        return image;
    }
    

    
    /**
     * 
     * @Title: 构造图片
     * @Description: 生成水印并返回java.awt.image.BufferedImage
     * @param buffImg
     *            源文件(BufferedImage)
     * @param waterFile
     *            水印文件(BufferedImage)
     * @param x
     *            距离右下角的X偏移量
     * @param y
     *            距离右下角的Y偏移量
     * @param alpha
     *            透明度, 选择值从0.0~1.0: 完全透明~完全不透明
     * @return BufferedImage
     * @throws IOException
     */
    public static BufferedImage overlyingImage(BufferedImage buffImg, BufferedImage waterImg, int x, int y, float alpha) throws IOException {

        // 创建Graphics2D对象,用在底图对象上绘图
        Graphics2D g2d = buffImg.createGraphics();
        int waterImgWidth = waterImg.getWidth();// 获取层图的宽度
        int waterImgHeight = waterImg.getHeight();// 获取层图的高度
        // 在图形和图像中实现混合和透明效果
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
        // 绘制
        g2d.drawImage(waterImg, x, y, waterImgWidth, waterImgHeight, null);
        g2d.dispose();// 释放图形上下文使用的系统资源
        return buffImg;
    }
    
    /**
     * 输出图片
     * 
     * @param buffImg
     *            图像拼接叠加之后的BufferedImage对象
     * @param savePath
     *            图像拼接叠加之后的保存路径
     */
    public static void generateSaveFile(BufferedImage buffImg, String savePath) {
        int temp = savePath.lastIndexOf(".") + 1;
        try {
            File outFile = new File(savePath);
            if(!outFile.exists()){
                outFile.createNewFile();
            }
            ImageIO.write(buffImg, savePath.substring(temp), outFile);
            System.out.println("ImageIO write...");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    
    
    /**
     * 待合并的两张图必须满足这样的前提,如果水平方向合并,则高度必须相等;如果是垂直方向合并,宽度必须相等。
     * mergeImage方法不做判断,自己判断。
     *
     * @param img1
     *            待合并的第一张图
     * @param img2
     *            带合并的第二张图
     * @param isHorizontal
     *            为true时表示水平方向合并,为false时表示垂直方向合并
     * @return 返回合并后的BufferedImage对象
     * @throws IOException
     */
    public static BufferedImage mergeImage(BufferedImage img1,
            BufferedImage img2, boolean isHorizontal) throws IOException {
        int w1 = img1.getWidth();
        int h1 = img1.getHeight();
        int w2 = img2.getWidth();
        int h2 = img2.getHeight();

        // 从图片中读取RGB
        int[] ImageArrayOne = new int[w1 * h1];
        ImageArrayOne = img1.getRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 逐行扫描图像中各个像素的RGB到数组中
        int[] ImageArrayTwo = new int[w2 * h2];
        ImageArrayTwo = img2.getRGB(0, 0, w2, h2, ImageArrayTwo, 0, w2);

        // 生成新图片
        BufferedImage DestImage = null;
        if (isHorizontal) { // 水平方向合并
            DestImage = new BufferedImage(w1+w2, h1, BufferedImage.TYPE_INT_RGB);
            DestImage.setRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 设置上半部分或左半部分的RGB
            DestImage.setRGB(w1, 0, w2, h2, ImageArrayTwo, 0, w2);
        } else { // 垂直方向合并
            DestImage = new BufferedImage(w1, h1 + h2, BufferedImage.TYPE_INT_RGB);
            DestImage.setRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 设置上半部分或左半部分的RGB
            DestImage.setRGB(0, h1, w2, h2, ImageArrayTwo, 0, w2); // 设置下半部分的RGB
        }

        return DestImage;
    }

    /**
     * Java 测试图片叠加方法
     */
    public static void overlyingImageTest() {

        String sourceFilePath = "D://test//test1.jpg";
        String waterFilePath = "D://test//test2.jpg";
        String saveFilePath = "D://test//overlyingImageNew.jpg";
        try {
            BufferedImage bufferImage1 = getBufferedImage(sourceFilePath);
            BufferedImage bufferImage2 = getBufferedImage(waterFilePath);

            // 构建叠加层
            BufferedImage buffImg = overlyingImage(bufferImage1, bufferImage2, 0, 0, 1.0f);
            // 输出水印图片
            generateSaveFile(buffImg, saveFilePath);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    
    
    /**
     * Java 测试图片合并方法
     */
    public static void imageMargeTest() {
        // 读取待合并的文件
        BufferedImage bi1 = null;
        BufferedImage bi2 = null;
        // 调用mergeImage方法获得合并后的图像
        BufferedImage destImg = null;
        System.out.println("下面是垂直合并的情况:");
        String saveFilePath = "D://test//new1.jpg";
        String divingPath = "D://test//new2.jpg";
        String margeImagePath = "D://test//margeNew.jpg";
        try {
            bi1 = getBufferedImage(saveFilePath);
            bi2 = getBufferedImage(divingPath);
            // 调用mergeImage方法获得合并后的图像
            destImg = mergeImage(bi1, bi2, false);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 保存图像
        generateSaveFile(destImg, margeImagePath);
        System.out.println("垂直合并完毕!");
    }

    public static void main(String[] args) {
        // 测试图片的叠加
        overlyingImageTest();
        // 测试图片的垂直合并
        imageMargeTest();
    }

} 
View Code

 

分类:

Java

技术点:

相关文章: