Java如何实现图片的叠加与拼接操作
关于Java实现图片的叠加与拼接的文章网络上确实很多,碰巧小编开发工作中也遇到这些问题,就做了简要的梳理,作为笔记以备不时之需。
Java对图片的处理主要使用的是BufferedImage类。
BufferedImage子类描述具有可访问图像数据缓冲区的Image。BufferedImage由图像数据的ColorModel和Raster组成。Raster的SampleModel中band的数量和类型必须与ColorModel所要求的数量和类型相匹配,以表示其颜色和alpha分量。所有BufferedImage对象的左上角坐标都为(0,0)。因此,用来构造BufferedImage的任何Raster都必须满足:minX=0且minY=0。此类依靠Raster的数据获取方法、数据设置方法,以及ColorModel的颜色特征化方法。
以上主要来源于官方文档,我们来时直接写实践代码吧。
首先将文件转化为BufferedImage对象,这里给出两种读取文件并转化为BufferedImage对象的方法。
/** *@paramfileUrl文件绝对路径或相对路径 *@return读取到的缓存图像 *@throwsIOException路径错误或者不存在该文件时抛出IO异常 */ publicstaticBufferedImagegetBufferedImage(StringfileUrl) throwsIOException{ Filef=newFile(fileUrl); returnImageIO.read(f); } /** *远程图片转BufferedImage *@paramdestUrl远程图片地址 *@return */ publicstaticBufferedImagegetBufferedImageDestUrl(StringdestUrl){ HttpURLConnectionconn=null; BufferedImageimage=null; try{ URLurl=newURL(destUrl); conn=(HttpURLConnection)url.openConnection(); if(conn.getResponseCode()==200){ image=ImageIO.read(conn.getInputStream()); returnimage; } }catch(Exceptione){ e.printStackTrace(); }finally{ conn.disconnect(); } returnimage; }
接下来是将BufferedImage对象保存到本地,具体方法如下:
/** *输出图片 *@parambuffImg图像拼接叠加之后的BufferedImage对象 *@paramsavePath图像拼接叠加之后的保存路径 */ publicstaticvoidgenerateSaveFile(BufferedImagebuffImg,StringsavePath){ inttemp=savePath.lastIndexOf(".")+1; try{ FileoutFile=newFile(savePath); if(!outFile.exists()){ outFile.createNewFile(); } ImageIO.write(buffImg,savePath.substring(temp),outFile); System.out.println("ImageIOwrite..."); }catch(IOExceptione){ e.printStackTrace(); } }
以上作为准备部分,现在开始图片叠加的实现方法:
/** * *@Title:构造图片 *@Description:生成水印并返回java.awt.image.BufferedImage *@parambuffImg源文件(BufferedImage) *@paramwaterFile水印文件(BufferedImage) *@paramx距离右下角的X偏移量 *@paramy距离右下角的Y偏移量 *@paramalpha透明度,选择值从0.0~1.0:完全透明~完全不透明 *@returnBufferedImage *@throwsIOException */ publicstaticBufferedImageoverlyingImage(BufferedImagebuffImg,BufferedImagewaterImg,intx,inty,floatalpha)throwsIOException{ //创建Graphics2D对象,用在底图对象上绘图 Graphics2Dg2d=buffImg.createGraphics(); intwaterImgWidth=waterImg.getWidth();//获取层图的宽度 intwaterImgHeight=waterImg.getHeight();//获取层图的高度 //在图形和图像中实现混合和透明效果 g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,alpha)); //绘制 g2d.drawImage(waterImg,x,y,waterImgWidth,waterImgHeight,null); g2d.dispose();//释放图形上下文使用的系统资源 returnbuffImg; }
图片拼接的实现方法:
/** *待合并的两张图必须满足这样的前提,如果水平方向合并,则高度必须相等;如果是垂直方向合并,宽度必须相等。 *mergeImage方法不做判断,自己判断。 *@paramimg1待合并的第一张图 *@paramimg2带合并的第二张图 *@paramisHorizontal为true时表示水平方向合并,为false时表示垂直方向合并 *@return返回合并后的BufferedImage对象 *@throwsIOException */ publicstaticBufferedImagemergeImage(BufferedImageimg1, BufferedImageimg2,booleanisHorizontal)throwsIOException{ intw1=img1.getWidth(); inth1=img1.getHeight(); intw2=img2.getWidth(); inth2=img2.getHeight(); //从图片中读取RGB int[]ImageArrayOne=newint[w1*h1]; ImageArrayOne=img1.getRGB(0,0,w1,h1,ImageArrayOne,0,w1);//逐行扫描图像中各个像素的RGB到数组中 int[]ImageArrayTwo=newint[w2*h2]; ImageArrayTwo=img2.getRGB(0,0,w2,h2,ImageArrayTwo,0,w2); //生成新图片 BufferedImageDestImage=null; if(isHorizontal){//水平方向合并 DestImage=newBufferedImage(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=newBufferedImage(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 } returnDestImage; }
测试方法如下:
/** *Java测试图片叠加方法 */ publicstaticvoidoverlyingImageTest(){ StringsourceFilePath="D://test//test1.jpg"; StringwaterFilePath="D://test//test2.jpg"; StringsaveFilePath="D://test//overlyingImageNew.jpg"; try{ BufferedImagebufferImage1=getBufferedImage(sourceFilePath); BufferedImagebufferImage2=getBufferedImage(waterFilePath); //构建叠加层 BufferedImagebuffImg=overlyingImage(bufferImage1,bufferImage2,0,0,1.0f); //输出水印图片 generateSaveFile(buffImg,saveFilePath); }catch(IOExceptione){ e.printStackTrace(); } } /** *Java测试图片合并方法 */ publicstaticvoidimageMargeTest(){ //读取待合并的文件 BufferedImagebi1=null; BufferedImagebi2=null; //调用mergeImage方法获得合并后的图像 BufferedImagedestImg=null; System.out.println("下面是垂直合并的情况:"); StringsaveFilePath="D://test//new1.jpg"; StringdivingPath="D://test//new2.jpg"; StringmargeImagePath="D://test//margeNew.jpg"; try{ bi1=getBufferedImage(saveFilePath); bi2=getBufferedImage(divingPath); //调用mergeImage方法获得合并后的图像 destImg=mergeImage(bi1,bi2,false); }catch(IOExceptione){ e.printStackTrace(); } //保存图像 generateSaveFile(destImg,margeImagePath); System.out.println("垂直合并完毕!"); } publicstaticvoidmain(String[]args){ //测试图片的叠加 overlyingImageTest(); //测试图片的垂直合并 imageMargeTest(); }
整体代码如下:
packageImagePackage; importjava.awt.AlphaComposite; importjava.awt.Graphics2D; importjava.awt.image.BufferedImage; importjava.io.File; importjava.io.IOException; importjava.net.HttpURLConnection; importjava.net.URL; importjavax.imageio.ImageIO; /** *该类实现了图片的合并功能,可以选择水平合并或者垂直合并。 *当然此例只是针对两个图片的合并,如果想要实现多个图片的合并,只需要自己实现方法BufferedImage *mergeImage(BufferedImage[]imgs,booleanisHorizontal)即可; *而且这个方法更加具有通用性,但是时间原因不实现了,方法和两张图片实现是一样的 */ publicclassImageMerge{ /** *@paramfileUrl *文件绝对路径或相对路径 *@return读取到的缓存图像 *@throwsIOException *路径错误或者不存在该文件时抛出IO异常 */ publicstaticBufferedImagegetBufferedImage(StringfileUrl) throwsIOException{ Filef=newFile(fileUrl); returnImageIO.read(f); } /** *远程图片转BufferedImage *@paramdestUrl远程图片地址 *@return */ publicstaticBufferedImagegetBufferedImageDestUrl(StringdestUrl){ HttpURLConnectionconn=null; BufferedImageimage=null; try{ URLurl=newURL(destUrl); conn=(HttpURLConnection)url.openConnection(); if(conn.getResponseCode()==200){ image=ImageIO.read(conn.getInputStream()); returnimage; } }catch(Exceptione){ e.printStackTrace(); }finally{ conn.disconnect(); } returnimage; } /** *输出图片 * *@parambuffImg *图像拼接叠加之后的BufferedImage对象 *@paramsavePath *图像拼接叠加之后的保存路径 */ publicstaticvoidgenerateSaveFile(BufferedImagebuffImg,StringsavePath){ inttemp=savePath.lastIndexOf(".")+1; try{ FileoutFile=newFile(savePath); if(!outFile.exists()){ outFile.createNewFile(); } ImageIO.write(buffImg,savePath.substring(temp),outFile); System.out.println("ImageIOwrite..."); }catch(IOExceptione){ e.printStackTrace(); } } /** * *@Title:构造图片 *@Description:生成水印并返回java.awt.image.BufferedImage *@parambuffImg *源文件(BufferedImage) *@paramwaterFile *水印文件(BufferedImage) *@paramx *距离右下角的X偏移量 *@paramy *距离右下角的Y偏移量 *@paramalpha *透明度,选择值从0.0~1.0:完全透明~完全不透明 *@returnBufferedImage *@throwsIOException */ publicstaticBufferedImageoverlyingImage(BufferedImagebuffImg,BufferedImagewaterImg,intx,inty,floatalpha)throwsIOException{ //创建Graphics2D对象,用在底图对象上绘图 Graphics2Dg2d=buffImg.createGraphics(); intwaterImgWidth=waterImg.getWidth();//获取层图的宽度 intwaterImgHeight=waterImg.getHeight();//获取层图的高度 //在图形和图像中实现混合和透明效果 g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,alpha)); //绘制 g2d.drawImage(waterImg,x,y,waterImgWidth,waterImgHeight,null); g2d.dispose();//释放图形上下文使用的系统资源 returnbuffImg; } /** *待合并的两张图必须满足这样的前提,如果水平方向合并,则高度必须相等;如果是垂直方向合并,宽度必须相等。 *mergeImage方法不做判断,自己判断。 * *@paramimg1 *待合并的第一张图 *@paramimg2 *带合并的第二张图 *@paramisHorizontal *为true时表示水平方向合并,为false时表示垂直方向合并 *@return返回合并后的BufferedImage对象 *@throwsIOException */ publicstaticBufferedImagemergeImage(BufferedImageimg1, BufferedImageimg2,booleanisHorizontal)throwsIOException{ intw1=img1.getWidth(); inth1=img1.getHeight(); intw2=img2.getWidth(); inth2=img2.getHeight(); //从图片中读取RGB int[]ImageArrayOne=newint[w1*h1]; ImageArrayOne=img1.getRGB(0,0,w1,h1,ImageArrayOne,0,w1);//逐行扫描图像中各个像素的RGB到数组中 int[]ImageArrayTwo=newint[w2*h2]; ImageArrayTwo=img2.getRGB(0,0,w2,h2,ImageArrayTwo,0,w2); //生成新图片 BufferedImageDestImage=null; if(isHorizontal){//水平方向合并 DestImage=newBufferedImage(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=newBufferedImage(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 } returnDestImage; } /** *Java测试图片叠加方法 */ publicstaticvoidoverlyingImageTest(){ StringsourceFilePath="D://test//test1.jpg"; StringwaterFilePath="D://test//test2.jpg"; StringsaveFilePath="D://test//overlyingImageNew.jpg"; try{ BufferedImagebufferImage1=getBufferedImage(sourceFilePath); BufferedImagebufferImage2=getBufferedImage(waterFilePath); //构建叠加层 BufferedImagebuffImg=overlyingImage(bufferImage1,bufferImage2,0,0,1.0f); //输出水印图片 generateSaveFile(buffImg,saveFilePath); }catch(IOExceptione){ e.printStackTrace(); } } /** *Java测试图片合并方法 */ publicstaticvoidimageMargeTest(){ //读取待合并的文件 BufferedImagebi1=null; BufferedImagebi2=null; //调用mergeImage方法获得合并后的图像 BufferedImagedestImg=null; System.out.println("下面是垂直合并的情况:"); StringsaveFilePath="D://test//new1.jpg"; StringdivingPath="D://test//new2.jpg"; StringmargeImagePath="D://test//margeNew.jpg"; try{ bi1=getBufferedImage(saveFilePath); bi2=getBufferedImage(divingPath); //调用mergeImage方法获得合并后的图像 destImg=mergeImage(bi1,bi2,false); }catch(IOExceptione){ e.printStackTrace(); } //保存图像 generateSaveFile(destImg,margeImagePath); System.out.println("垂直合并完毕!"); } publicstaticvoidmain(String[]args){ //测试图片的叠加 overlyingImageTest(); //测试图片的垂直合并 imageMargeTest(); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。