leo

不积跬步,无以至千里。不积小流无,以成江海。

Java imageIO处理图像

  1. package com.adam.dev.pic.easyImage;  
  2. import java.awt.AlphaComposite;  
  3. import java.awt.Color;  
  4. import java.awt.Font;  
  5. import java.awt.Graphics;  
  6. import java.awt.Graphics2D;  
  7. import java.awt.Point;  
  8. import java.awt.Rectangle;  
  9. import java.awt.color.ColorSpace;  
  10. import java.awt.image.BufferedImage;  
  11. import java.awt.image.ColorConvertOp;  
  12. import java.io.BufferedReader;  
  13. import java.io.File;  
  14. import java.io.FileInputStream;  
  15. import java.io.FileOutputStream;  
  16. import java.io.FileReader;  
  17. import java.io.IOException;  
  18. import java.io.InputStream;  
  19. import java.io.OutputStream;  
  20. import java.util.Iterator;  
  21. import java.util.List;  
  22.   
  23. import javax.imageio.ImageIO;  
  24. import javax.imageio.ImageReadParam;  
  25. import javax.imageio.ImageReader;  
  26. import javax.imageio.stream.ImageInputStream;  
  27.   
  28. import com.sun.image.codec.jpeg.JPEGCodec;  
  29. import com.sun.image.codec.jpeg.JPEGImageEncoder;  
  30.   
  31. /** 
  32.  * @author adam.胡升阳 
  33.  * 创建日期 2012-2-29 
  34.  */  
  35. public class OperateImage{  
  36.   
  37.     public OperateImage() {  
  38.         super();  
  39.     }  
  40.   
  41.     /**  
  42.      * 对图片裁剪,并把裁剪新图片保存  
  43.      * @param srcPath 读取源图片路径 
  44.      * @param toPath    写入图片路径 
  45.      * @param x 剪切起始点x坐标 
  46.      * @param y 剪切起始点y坐标 
  47.      * @param width 剪切宽度 
  48.      * @param height     剪切高度 
  49.      * @param readImageFormat  读取图片格式 
  50.      * @param writeImageFormat 写入图片格式 
  51.      * @throws IOException 
  52.      */  
  53.     public void cropImage(String srcPath,String toPath,  
  54.             int x,int y,int width,int height,  
  55.             String readImageFormat,String writeImageFormat) throws IOException{     
  56.         FileInputStream fis = null ;  
  57.         ImageInputStream iis =null ;  
  58.         try{     
  59.             //读取图片文件   
  60.             fis = new FileInputStream(srcPath);   
  61.             Iterator it = ImageIO.getImageReadersByFormatName(readImageFormat);   
  62.             ImageReader reader = (ImageReader) it.next();   
  63.             //获取图片流    
  64.             iis = ImageIO.createImageInputStream(fis);    
  65.             reader.setInput(iis,true) ;  
  66.             ImageReadParam param = reader.getDefaultReadParam();   
  67.             //定义一个矩形   
  68.             Rectangle rect = new Rectangle(x, y, width, height);   
  69.             //提供一个 BufferedImage,将其用作解码像素数据的目标。    
  70.             param.setSourceRegion(rect);  
  71.             BufferedImage bi = reader.read(0,param);                  
  72.             //保存新图片    
  73.             ImageIO.write(bi, writeImageFormat, new File(toPath));       
  74.         }finally{  
  75.             if(fis!=null)  
  76.                 fis.close();         
  77.             if(iis!=null)  
  78.                iis.close();   
  79.         }   
  80.     }  
  81.   
  82.     /** 
  83.      * 按倍率缩小图片 
  84.      * @param srcImagePath 读取图片路径 
  85.      * @param toImagePath 写入图片路径 
  86.      * @param widthRatio    宽度缩小比例 
  87.      * @param heightRatio    高度缩小比例 
  88.      * @throws IOException 
  89.      */  
  90.     public void reduceImageByRatio(String srcImagePath,String toImagePath,int widthRatio,int heightRatio) throws IOException{  
  91.         FileOutputStream out = null;  
  92.         try{  
  93.             //读入文件     
  94.             File file = new File(srcImagePath);    
  95.             // 构造Image对象     
  96.             BufferedImage src = javax.imageio.ImageIO.read(file);    
  97.             int width = src.getWidth();    
  98.             int height = src.getHeight();    
  99.             // 缩小边长    
  100.             BufferedImage tag = new BufferedImage(width / widthRatio, height / heightRatio, BufferedImage.TYPE_INT_RGB);    
  101.             // 绘制 缩小  后的图片    
  102.             tag.getGraphics().drawImage(src, 00, width / widthRatio, height / heightRatio, null);    
  103.             out = new FileOutputStream(toImagePath);    
  104.             JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);    
  105.             encoder.encode(tag);    
  106.         }catch(Exception e){  
  107.             e.printStackTrace();  
  108.         }finally{  
  109.             if(out != null){  
  110.                 out.close();    
  111.             }  
  112.         }  
  113.     }  
  114.   
  115.     /** 
  116.      * 长高等比例缩小图片 
  117.      * @param srcImagePath 读取图片路径 
  118.      * @param toImagePath 写入图片路径 
  119.      * @param ratio 缩小比例 
  120.      * @throws IOException 
  121.      */  
  122.     public void reduceImageEqualProportion(String srcImagePath,String toImagePath,int ratio) throws IOException{  
  123.         FileOutputStream out = null;  
  124.         try{  
  125.             //读入文件     
  126.             File file = new File(srcImagePath);    
  127.             // 构造Image对象     
  128.             BufferedImage src = javax.imageio.ImageIO.read(file);    
  129.             int width = src.getWidth();    
  130.             int height = src.getHeight();    
  131.             // 缩小边长    
  132.             BufferedImage tag = new BufferedImage(width / ratio, height / ratio, BufferedImage.TYPE_INT_RGB);    
  133.             // 绘制 缩小  后的图片    
  134.             tag.getGraphics().drawImage(src, 00, width / ratio, height / ratio, null);    
  135.             out = new FileOutputStream(toImagePath);    
  136.             JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);    
  137.             encoder.encode(tag);    
  138.         }catch(Exception e){  
  139.             e.printStackTrace();  
  140.         }finally{  
  141.             if(out != null){  
  142.                 out.close();    
  143.             }  
  144.         }  
  145.     }  
  146.       
  147.     /** 
  148.      * 按倍率放大图片 
  149.      * @param srcImagePath 读取图形路径 
  150.      * @param toImagePath 写入入行路径 
  151.      * @param widthRatio    宽度放大比例 
  152.      * @param heightRatio 高度放大比例 
  153.      * @throws IOException 
  154.      */  
  155.     public void enlargementImageByRatio(String srcImagePath,String toImagePath,int widthRatio,int heightRatio) throws IOException{  
  156.         FileOutputStream out = null;  
  157.         try{  
  158.             //读入文件     
  159.             File file = new File(srcImagePath);    
  160.             // 构造Image对象     
  161.             BufferedImage src = javax.imageio.ImageIO.read(file);    
  162.             int width = src.getWidth();    
  163.             int height = src.getHeight();    
  164.             // 放大边长   
  165.             BufferedImage tag = new BufferedImage(width * widthRatio, height * heightRatio, BufferedImage.TYPE_INT_RGB);    
  166.             //绘制放大后的图片   
  167.             tag.getGraphics().drawImage(src, 00, width * widthRatio, height * heightRatio, null);    
  168.             out = new FileOutputStream(toImagePath);    
  169.             JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);    
  170.             encoder.encode(tag);    
  171.         }catch(Exception e){  
  172.             e.printStackTrace();  
  173.         }finally{  
  174.             if(out != null){  
  175.                 out.close();    
  176.             }  
  177.         }  
  178.     }  
  179.       
  180.       
  181.     /** 
  182.      * 长高等比例放大图片 
  183.      * @param srcImagePath 读取图形路径 
  184.      * @param toImagePath 写入入行路径 
  185.      * @param ratio 放大比例 
  186.      * @throws IOException 
  187.      */  
  188.     public void enlargementImageEqualProportion(String srcImagePath,String toImagePath,int ratio) throws IOException{  
  189.         FileOutputStream out = null;  
  190.         try{  
  191.             //读入文件     
  192.             File file = new File(srcImagePath);    
  193.             // 构造Image对象     
  194.             BufferedImage src = javax.imageio.ImageIO.read(file);    
  195.             int width = src.getWidth();    
  196.             int height = src.getHeight();    
  197.             // 放大边长   
  198.             BufferedImage tag = new BufferedImage(width * ratio, height * ratio, BufferedImage.TYPE_INT_RGB);    
  199.             //绘制放大后的图片   
  200.             tag.getGraphics().drawImage(src, 00, width * ratio, height * ratio, null);    
  201.             out = new FileOutputStream(toImagePath);    
  202.             JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);    
  203.             encoder.encode(tag);    
  204.         }catch(Exception e){  
  205.             e.printStackTrace();  
  206.         }finally{  
  207.             if(out != null){  
  208.                 out.close();    
  209.             }  
  210.         }  
  211.     }  
  212.       
  213.     /** 
  214.      * 重置图形的边长大小 
  215.      * @param srcImagePath  
  216.      * @param toImagePath 
  217.      * @param width 
  218.      * @param height 
  219.      * @throws IOException 
  220.      */  
  221.     public void resizeImage(String srcImagePath,String toImagePath,int width,int height) throws IOException{  
  222.         FileOutputStream out = null;  
  223.         try{  
  224.             //读入文件     
  225.             File file = new File(srcImagePath);    
  226.             // 构造Image对象     
  227.             BufferedImage src = javax.imageio.ImageIO.read(file);    
  228.             // 放大边长   
  229.             BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);    
  230.             //绘制放大后的图片   
  231.             tag.getGraphics().drawImage(src, 00, width, height, null);    
  232.             out = new FileOutputStream(toImagePath);    
  233.             JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);    
  234.             encoder.encode(tag);    
  235.         }catch(Exception e){  
  236.             e.printStackTrace();  
  237.         }finally{  
  238.             if(out != null){  
  239.                 out.close();    
  240.             }  
  241.         }  
  242.     }  
  243.       
  244.     /** 
  245.      * 横向拼接图片(两张) 
  246.      * @param firstSrcImagePath 第一张图片的路径 
  247.      * @param secondSrcImagePath    第二张图片的路径 
  248.      * @param imageFormat   拼接生成图片的格式 
  249.      * @param toPath    拼接生成图片的路径 
  250.      */  
  251.     public void joinImagesHorizontal(String firstSrcImagePath, String secondSrcImagePath,String imageFormat, String toPath){    
  252.         try {    
  253.             //读取第一张图片       
  254.             File  fileOne  =  new  File(firstSrcImagePath);      
  255.             BufferedImage  imageOne = ImageIO.read(fileOne);      
  256.             int  width  =  imageOne.getWidth();//图片宽度       
  257.             int  height  =  imageOne.getHeight();//图片高度       
  258.             //从图片中读取RGB       
  259.             int[]  imageArrayOne  =  new  int[width*height];      
  260.             imageArrayOne  =  imageOne.getRGB(0,0,width,height,imageArrayOne,0,width);      
  261.              
  262.             //对第二张图片做相同的处理       
  263.             File  fileTwo  =  new  File(secondSrcImagePath);      
  264.             BufferedImage  imageTwo  =  ImageIO.read(fileTwo);   
  265.             int width2 = imageTwo.getWidth();  
  266.             int height2 = imageTwo.getHeight();  
  267.             int[]   ImageArrayTwo  =  new  int[width2*height2];      
  268.             ImageArrayTwo  =  imageTwo.getRGB(0,0,width,height,ImageArrayTwo,0,width);      
  269.             //ImageArrayTwo  =  imageTwo.getRGB(0,0,width2,height2,ImageArrayTwo,0,width2);    
  270.              
  271.             //生成新图片   
  272.             //int height3 = (height>height2 || height==height2)?height:height2;   
  273.             BufferedImage  imageNew  =  new  BufferedImage(width*2,height,BufferedImage.TYPE_INT_RGB);      
  274.             //BufferedImage  imageNew  =  new  BufferedImage(width+width2,height3,BufferedImage.TYPE_INT_RGB);       
  275.             imageNew.setRGB(0,0,width,height,imageArrayOne,0,width);//设置左半部分的RGB     
  276.             imageNew.setRGB(width,0,width,height,ImageArrayTwo,0,width);//设置右半部分的RGB    
  277.             //imageNew.setRGB(width,0,width2,height2,ImageArrayTwo,0,width2);//设置右半部分的RGB       
  278.              
  279.             File  outFile  =  new  File(toPath);      
  280.             ImageIO.write(imageNew,  imageFormat,  outFile);//写图片   
  281.         } catch (Exception e) {    
  282.             e.printStackTrace();    
  283.         }    
  284.     }  
  285.       
  286.     /** 
  287.      * 横向拼接一组(多张)图像 
  288.      * @param pics  将要拼接的图像 
  289.      * @param type 图像写入格式 
  290.      * @param dst_pic 图像写入路径 
  291.      * @return 
  292.      */  
  293.     public  boolean joinImageListHorizontal(String[] pics, String type, String dst_pic) {     
  294.         try {    
  295.             int len = pics.length;    
  296.             if (len < 1) {    
  297.                 System.out.println("pics len < 1");    
  298.                 return false;    
  299.             }    
  300.             File[] src = new File[len];    
  301.             BufferedImage[] images = new BufferedImage[len];    
  302.             int[][] imageArrays = new int[len][];    
  303.             for (int i = 0; i < len; i++) {    
  304.                 src[i] = new File(pics[i]);    
  305.                 images[i] = ImageIO.read(src[i]);    
  306.                 int width = images[i].getWidth();    
  307.                 int height = images[i].getHeight();    
  308.                 imageArrays[i] = new int[width * height];// 从图片中读取RGB       
  309.                 imageArrays[i] = images[i].getRGB(00, width, height,  imageArrays[i], 0, width);    
  310.             }    
  311.               
  312.             int dst_width = 0;    
  313.             int dst_height = images[0].getHeight();    
  314.             for (int i = 0; i < images.length; i++) {    
  315.                 dst_height = dst_height > images[i].getHeight() ? dst_height : images[i].getHeight();    
  316.                 dst_width += images[i].getWidth();  
  317.             }    
  318.             //System.out.println(dst_width);     
  319.             //System.out.println(dst_height);     
  320.             if (dst_height < 1) {    
  321.                 System.out.println("dst_height < 1");    
  322.                 return false;    
  323.             }   
  324.             /* 
  325.              * 生成新图片 
  326.              */     
  327.             BufferedImage ImageNew = new BufferedImage(dst_width, dst_height,  BufferedImage.TYPE_INT_RGB);    
  328.             int width_i = 0;  
  329.             for (int i = 0; i < images.length; i++) {    
  330.                 ImageNew.setRGB(width_i, 0, images[i].getWidth(), dst_height,  imageArrays[i], 0, images[i].getWidth());    
  331.                 width_i += images[i].getWidth();  
  332.             }    
  333.             File outFile = new File(dst_pic);    
  334.             ImageIO.write(ImageNew, type, outFile);// 写图片      
  335.         } catch (Exception e) {    
  336.             e.printStackTrace();    
  337.             return false;    
  338.         }    
  339.         return true;    
  340.     }  
  341.       
  342.     /** 
  343.      * 纵向拼接图片(两张) 
  344.      * @param firstSrcImagePath 读取的第一张图片 
  345.      * @param secondSrcImagePath    读取的第二张图片 
  346.      * @param imageFormat 图片写入格式 
  347.      * @param toPath    图片写入路径 
  348.      */  
  349.     public void joinImagesVertical(String firstSrcImagePath, String secondSrcImagePath,String imageFormat, String toPath){    
  350.         try {    
  351.             //读取第一张图片       
  352.             File  fileOne  =  new  File(firstSrcImagePath);      
  353.             BufferedImage  imageOne = ImageIO.read(fileOne);      
  354.             int  width  =  imageOne.getWidth();//图片宽度       
  355.             int  height  =  imageOne.getHeight();//图片高度       
  356.             //从图片中读取RGB       
  357.             int[]  imageArrayOne  =  new  int[width*height];      
  358.             imageArrayOne  =  imageOne.getRGB(0,0,width,height,imageArrayOne,0,width);      
  359.          
  360.             //对第二张图片做相同的处理       
  361.             File  fileTwo  =  new  File(secondSrcImagePath);      
  362.             BufferedImage  imageTwo  =  ImageIO.read(fileTwo);   
  363.             int width2 = imageTwo.getWidth();  
  364.             int height2 = imageTwo.getHeight();  
  365.             int[]   ImageArrayTwo  =  new  int[width2*height2];      
  366.             ImageArrayTwo  =  imageTwo.getRGB(0,0,width,height,ImageArrayTwo,0,width);      
  367.             //ImageArrayTwo  =  imageTwo.getRGB(0,0,width2,height2,ImageArrayTwo,0,width2);    
  368.          
  369.             //生成新图片   
  370.             //int width3 = (width>width2 || width==width2)?width:width2;   
  371.             BufferedImage  imageNew  =  new  BufferedImage(width,height*2,BufferedImage.TYPE_INT_RGB);      
  372.             //BufferedImage  imageNew  =  new  BufferedImage(width3,height+height2,BufferedImage.TYPE_INT_RGB);       
  373.             imageNew.setRGB(0,0,width,height,imageArrayOne,0,width);//设置上半部分的RGB       
  374.             imageNew.setRGB(0,height,width,height,ImageArrayTwo,0,width);//设置下半部分的RGB   
  375.             //imageNew.setRGB(0,height,width2,height2,ImageArrayTwo,0,width2);//设置下半部分的RGB       
  376.          
  377.             File  outFile  =  new  File(toPath);      
  378.             ImageIO.write(imageNew,  imageFormat,  outFile);//写图片   
  379.         } catch (Exception e) {    
  380.             e.printStackTrace();    
  381.         }    
  382.     }  
  383.       
  384.     /** 
  385.      * 纵向拼接一组(多张)图像 
  386.      * @param pics      将要拼接的图像数组 
  387.      * @param type  写入图像类型 
  388.      * @param dst_pic   写入图像路径 
  389.      * @return 
  390.      */  
  391.     public  boolean joinImageListVertical(String[] pics, String type, String dst_pic) {     
  392.         try {    
  393.             int len = pics.length;    
  394.             if (len < 1) {    
  395.                 System.out.println("pics len < 1");    
  396.                 return false;    
  397.             }    
  398.              File[] src = new File[len];    
  399.              BufferedImage[] images = new BufferedImage[len];    
  400.              int[][] imageArrays = new int[len][];    
  401.              for (int i = 0; i < len; i++) {    
  402.                 //System.out.println(i);   
  403.                 src[i] = new File(pics[i]);    
  404.                 images[i] = ImageIO.read(src[i]);    
  405.                 int width = images[i].getWidth();    
  406.                 int height = images[i].getHeight();    
  407.                 imageArrays[i] = new int[width * height];// 从图片中读取RGB      
  408.                 imageArrays[i] = images[i].getRGB(00, width, height,  imageArrays[i], 0, width);    
  409.             }    
  410.                
  411.             int dst_height = 0;    
  412.             int dst_width = images[0].getWidth();    
  413.             for (int i = 0; i < images.length; i++) {    
  414.                 dst_width = dst_width > images[i].getWidth() ? dst_width : images[i].getWidth();    
  415.                 dst_height += images[i].getHeight();    
  416.             }    
  417.             //System.out.println(dst_width);     
  418.             //System.out.println(dst_height);     
  419.             if (dst_height < 1) {    
  420.                 System.out.println("dst_height < 1");    
  421.                 return false;    
  422.             }    
  423.             /* 
  424.              * 生成新图片 
  425.              */     
  426.             BufferedImage ImageNew = new BufferedImage(dst_width, dst_height,  BufferedImage.TYPE_INT_RGB);    
  427.             int height_i = 0;    
  428.             for (int i = 0; i < images.length; i++) {    
  429.                 ImageNew.setRGB(0, height_i, dst_width, images[i].getHeight(),  imageArrays[i], 0, dst_width);    
  430.                 height_i += images[i].getHeight();    
  431.             }    
  432.             File outFile = new File(dst_pic);    
  433.             ImageIO.write(ImageNew, type, outFile);// 写图片      
  434.         } catch (Exception e) {    
  435.             e.printStackTrace();    
  436.             return false;    
  437.         }    
  438.         return true;    
  439.     }    
  440.       
  441.     /** 
  442.      * 合并图片(按指定初始x、y坐标将附加图片贴到底图之上) 
  443.      * @param negativeImagePath 背景图片路径 
  444.      * @param additionImagePath 附加图片路径 
  445.      * @param x 附加图片的起始点x坐标 
  446.      * @param y  附加图片的起始点y坐标 
  447.      * @param toPath 图片写入路径 
  448.      * @throws IOException 
  449.      */  
  450.     public void mergeBothImage(String negativeImagePath,String additionImagePath,int x,int y,String toPath ) throws IOException{  
  451.         InputStream is= null;  
  452.         InputStream is2= null;  
  453.         OutputStream os = null;  
  454.         try{  
  455.             is=new FileInputStream(negativeImagePath);  
  456.             is2=new FileInputStream(additionImagePath);  
  457.             BufferedImage image=ImageIO.read(is);  
  458.             BufferedImage image2=ImageIO.read(is2);  
  459.             Graphics g=image.getGraphics();  
  460.             g.drawImage(image2,x,y,null);  
  461.             os = new FileOutputStream(toPath);  
  462.             JPEGImageEncoder enc=JPEGCodec.createJPEGEncoder(os);  
  463.             enc.encode(image);  
  464.         }catch(Exception e){  
  465.             e.printStackTrace();  
  466.         }finally{  
  467.             if(os != null){  
  468.                 os.close();  
  469.             }  
  470.             if(is2 != null){  
  471.                 is2.close();  
  472.             }  
  473.             if(is != null){  
  474.                 is.close();  
  475.             }  
  476.         }  
  477.     }  
  478.       
  479.     /**  
  480.      * 将一组图片一次性附加合并到底图上 
  481.      * @param negativeImagePath     源图像(底图)路径 
  482.      * @param additionImageList 附加图像信息列表 
  483.      * @param imageFormat   图像写入格式 
  484.      * @param toPath    图像写入路径 
  485.      * @throws IOException 
  486.      */  
  487.     public void mergeImageList(String negativeImagePath,List additionImageList,String imageFormat, String toPath) throws IOException{  
  488.         InputStream is= null;  
  489.         InputStream is2= null;  
  490.         OutputStream os = null;  
  491.         try{  
  492.             is=new FileInputStream(negativeImagePath);  
  493.             BufferedImage image=ImageIO.read(is);  
  494.             //Graphics g=image.getGraphics();   
  495.             Graphics2D g = image.createGraphics();;  
  496.             BufferedImage image2 = null;  
  497.             if(additionImageList != null){  
  498.                 for(int i=0;i<additionImageList.size();i++){  
  499.                     //解析附加图片信息:x坐标、 y坐标、 additionImagePath附加图片路径   
  500.                     //图片信息存储在一个数组中   
  501.                     String[] additionImageInfo = (String[]) additionImageList.get(i);  
  502.                     int x = Integer.parseInt(additionImageInfo[0]);  
  503.                     int y = Integer.parseInt(additionImageInfo[1]);  
  504.                     String additionImagePath = additionImageInfo[2];  
  505.                     //读取文件输入流,并合并图片   
  506.                     is2 = new FileInputStream(additionImagePath);  
  507.                     //System.out.println(x+"  :  "+y+"  :  "+additionImagePath);   
  508.                     image2 = ImageIO.read(is2);  
  509.                     g.drawImage(image2,x,y,null);  
  510.                 }  
  511.             }  
  512.             os = new FileOutputStream(toPath);  
  513.             ImageIO.write(image,  imageFormat,  os);//写图片   
  514.             //JPEGImageEncoder enc=JPEGCodec.createJPEGEncoder(os);   
  515.             //enc.encode(image);   
  516.         }catch(Exception e){  
  517.             e.printStackTrace();  
  518.         }finally{  
  519.             if(os != null){  
  520.                 os.close();  
  521.             }  
  522.             if(is2 != null){  
  523.                 is2.close();  
  524.             }  
  525.             if(is != null){  
  526.                 is.close();  
  527.             }  
  528.         }  
  529.     }  
  530.       
  531.     /** 
  532.      * 将附加图片合并到底图的左上角 
  533.      * @param negativeImagePath 底图路径 
  534.      * @param additionImagePath 附加图片路径 
  535.      * @param toPath    合成图片写入路径 
  536.      * @throws IOException 
  537.      */  
  538.     public void mergeBothImageTopleftcorner(String negativeImagePath,String additionImagePath,String toPath ) throws IOException{  
  539.         InputStream is= null;  
  540.         InputStream is2= null;  
  541.         OutputStream os = null;  
  542.         try{  
  543.             is=new FileInputStream(negativeImagePath);  
  544.             is2=new FileInputStream(additionImagePath);  
  545.             BufferedImage image=ImageIO.read(is);  
  546.             BufferedImage image2=ImageIO.read(is2);  
  547.             Graphics g=image.getGraphics();  
  548.             g.drawImage(image2,0,0,null);  
  549.             os = new FileOutputStream(toPath);  
  550.             JPEGImageEncoder enc=JPEGCodec.createJPEGEncoder(os);  
  551.             enc.encode(image);  
  552.         }catch(Exception e){  
  553.             e.printStackTrace();  
  554.         }finally{  
  555.             if(os != null){  
  556.                 os.close();  
  557.             }  
  558.             if(is2 != null){  
  559.                 is2.close();  
  560.             }  
  561.             if(is != null){  
  562.                 is.close();  
  563.             }  
  564.         }  
  565.     }  
  566.       
  567.     /** 
  568.      * 将附加图片合并到底图的右上角 
  569.      * @param negativeImagePath 底图路径 
  570.      * @param additionImagePath 附加图片路径 
  571.      * @param toPath    合成图片写入路径 
  572.      * @throws IOException 
  573.      */  
  574.     public void mergeBothImageToprightcorner(String negativeImagePath,String additionImagePath,String toPath ) throws IOException{  
  575.         InputStream is= null;  
  576.         InputStream is2= null;  
  577.         OutputStream os = null;  
  578.         try{  
  579.             is=new FileInputStream(negativeImagePath);  
  580.             is2=new FileInputStream(additionImagePath);  
  581.             BufferedImage image=ImageIO.read(is);  
  582.             BufferedImage image2=ImageIO.read(is2);  
  583.             Graphics g=image.getGraphics();  
  584.             g.drawImage(image2,image.getWidth()-image2.getWidth(),0,null);  
  585.             os = new FileOutputStream(toPath);  
  586.             JPEGImageEncoder enc=JPEGCodec.createJPEGEncoder(os);  
  587.             enc.encode(image);  
  588.         }catch(Exception e){  
  589.             e.printStackTrace();  
  590.         }finally{  
  591.             if(os != null){  
  592.                 os.close();  
  593.             }  
  594.             if(is2 != null){  
  595.                 is2.close();  
  596.             }  
  597.             if(is != null){  
  598.                 is.close();  
  599.             }  
  600.         }  
  601.     }  
  602.       
  603.     /** 
  604.      * 将附加图片合并到底图的左下角 
  605.      * @param negativeImagePath 底图路径 
  606.      * @param additionImagePath 附加图片路径 
  607.      * @param toPath    合成图片写入路径 
  608.      * @throws IOException 
  609.      */  
  610.     public void mergeBothImageLeftbottom(String negativeImagePath,String additionImagePath,String toPath ) throws IOException{  
  611.         InputStream is= null;  
  612.         InputStream is2= null;  
  613.         OutputStream os = null;  
  614.         try{  
  615.             is=new FileInputStream(negativeImagePath);  
  616.             is2=new FileInputStream(additionImagePath);  
  617.             BufferedImage image=ImageIO.read(is);  
  618.             BufferedImage image2=ImageIO.read(is2);  
  619.             Graphics g=image.getGraphics();  
  620.             g.drawImage(image2,0,image.getHeight()-image2.getHeight(),null);  
  621.             os = new FileOutputStream(toPath);  
  622.             JPEGImageEncoder enc=JPEGCodec.createJPEGEncoder(os);  
  623.             enc.encode(image);  
  624.         }catch(Exception e){  
  625.             e.printStackTrace();  
  626.         }finally{  
  627.             if(os != null){  
  628.                 os.close();  
  629.             }  
  630.             if(is2 != null){  
  631.                 is2.close();  
  632.             }  
  633.             if(is != null){  
  634.                 is.close();  
  635.             }  
  636.         }  
  637.     }  
  638.       
  639.     /** 
  640.      * 将附加图片合并到底图的左下角 
  641.      * @param negativeImagePath 底图路径 
  642.      * @param additionImagePath 附加图片路径 
  643.      * @param toPath    合成图片写入路径 
  644.      * @throws IOException 
  645.      */  
  646.     public void mergeBothImageRightbottom(String negativeImagePath,String additionImagePath,String toPath ) throws IOException{  
  647.         InputStream is= null;  
  648.         InputStream is2= null;  
  649.         OutputStream os = null;  
  650.         try{  
  651.             is=new FileInputStream(negativeImagePath);  
  652.             is2=new FileInputStream(additionImagePath);  
  653.             BufferedImage image=ImageIO.read(is);  
  654.             BufferedImage image2=ImageIO.read(is2);  
  655.             Graphics g=image.getGraphics();  
  656.             g.drawImage(image2,image.getWidth()-image2.getWidth(),image.getHeight()-image2.getHeight(),null);  
  657.             os = new FileOutputStream(toPath);  
  658.             JPEGImageEncoder enc=JPEGCodec.createJPEGEncoder(os);  
  659.             enc.encode(image);  
  660.         }catch(Exception e){  
  661.             e.printStackTrace();  
  662.         }finally{  
  663.             if(os != null){  
  664.                 os.close();  
  665.             }  
  666.             if(is2 != null){  
  667.                 is2.close();  
  668.             }  
  669.             if(is != null){  
  670.                 is.close();  
  671.             }  
  672.         }  
  673.     }  
  674.       
  675.     /** 
  676.      * 将附加图片合并到底图的正中央 
  677.      * @param negativeImagePath 底图路径 
  678.      * @param additionImagePath 附加图片路径 
  679.      * @param toPath    合成图片写入路径 
  680.      * @throws IOException 
  681.      */  
  682.     public void mergeBothImageCenter(String negativeImagePath,String additionImagePath,String toPath ) throws IOException{  
  683.         InputStream is= null;  
  684.         InputStream is2= null;  
  685.         OutputStream os = null;  
  686.         try{  
  687.             is=new FileInputStream(negativeImagePath);  
  688.             is2=new FileInputStream(additionImagePath);  
  689.             BufferedImage image=ImageIO.read(is);  
  690.             BufferedImage image2=ImageIO.read(is2);  
  691.             Graphics g=image.getGraphics();  
  692.             g.drawImage(image2,image.getWidth()/2-image2.getWidth()/2,image.getHeight()/2-image2.getHeight()/2,null);  
  693.             os = new FileOutputStream(toPath);  
  694.             JPEGImageEncoder enc=JPEGCodec.createJPEGEncoder(os);  
  695.             enc.encode(image);  
  696.         }catch(Exception e){  
  697.             e.printStackTrace();  
  698.         }finally{  
  699.             if(os != null){  
  700.                 os.close();  
  701.             }  
  702.             if(is2 != null){  
  703.                 is2.close();  
  704.             }  
  705.             if(is != null){  
  706.                 is.close();  
  707.             }  
  708.         }  
  709.     }  
  710.       
  711.     /** 
  712.      * 将附加图片合并到底图的上边中央 
  713.      * @param negativeImagePath 底图路径 
  714.      * @param additionImagePath 附加图片路径 
  715.      * @param toPath    合成图片写入路径 
  716.      * @throws IOException 
  717.      */  
  718.     public void mergeBothImageTopcenter(String negativeImagePath,String additionImagePath,String toPath ) throws IOException{  
  719.         InputStream is= null;  
  720.         InputStream is2= null;  
  721.         OutputStream os = null;  
  722.         try{  
  723.             is=new FileInputStream(negativeImagePath);  
  724.             is2=new FileInputStream(additionImagePath);  
  725.             BufferedImage image=ImageIO.read(is);  
  726.             BufferedImage image2=ImageIO.read(is2);  
  727.             Graphics g=image.getGraphics();  
  728.             g.drawImage(image2,image.getWidth()/2-image2.getWidth()/2,0,null);  
  729.             os = new FileOutputStream(toPath);  
  730.             JPEGImageEncoder enc=JPEGCodec.createJPEGEncoder(os);  
  731.             enc.encode(image);  
  732.         }catch(Exception e){  
  733.             e.printStackTrace();  
  734.         }finally{  
  735.             if(os != null){  
  736.                 os.close();  
  737.             }  
  738.             if(is2 != null){  
  739.                 is2.close();  
  740.             }  
  741.             if(is != null){  
  742.                 is.close();  
  743.             }  
  744.         }  
  745.     }  
  746.       
  747.     /** 
  748.      * 将附加图片合并到底图的下边中央 
  749.      * @param negativeImagePath 底图路径 
  750.      * @param additionImagePath 附加图片路径 
  751.      * @param toPath    合成图片写入路径 
  752.      * @throws IOException 
  753.      */  
  754.     public void mergeBothImageBottomcenter(String negativeImagePath,String additionImagePath,String toPath ) throws IOException{  
  755.         InputStream is= null;  
  756.         InputStream is2= null;  
  757.         OutputStream os = null;  
  758.         try{  
  759.             is=new FileInputStream(negativeImagePath);  
  760.             is2=new FileInputStream(additionImagePath);  
  761.             BufferedImage image=ImageIO.read(is);  
  762.             BufferedImage image2=ImageIO.read(is2);  
  763.             Graphics g=image.getGraphics();  
  764.             g.drawImage(image2,image.getWidth()/2-image2.getWidth()/2,image.getHeight()-image2.getHeight(),null);  
  765.             os = new FileOutputStream(toPath);  
  766.             JPEGImageEncoder enc=JPEGCodec.createJPEGEncoder(os);  
  767.             enc.encode(image);  
  768.         }catch(Exception e){  
  769.             e.printStackTrace();  
  770.         }finally{  
  771.             if(os != null){  
  772.                 os.close();  
  773.             }  
  774.             if(is2 != null){  
  775.                 is2.close();  
  776.             }  
  777.             if(is != null){  
  778.                 is.close();  
  779.             }  
  780.         }  
  781.     }  
  782.       
  783.     /** 
  784.      * 将附加图片合并到底图的左边中央 
  785.      * @param negativeImagePath 底图路径 
  786.      * @param additionImagePath 附加图片路径 
  787.      * @param toPath    合成图片写入路径 
  788.      * @throws IOException 
  789.      */  
  790.     public void mergeBothImageLeftcenter(String negativeImagePath,String additionImagePath,String toPath ) throws IOException{  
  791.         InputStream is= null;  
  792.         InputStream is2= null;  
  793.         OutputStream os = null;  
  794.         try{  
  795.             is=new FileInputStream(negativeImagePath);  
  796.             is2=new FileInputStream(additionImagePath);  
  797.             BufferedImage image=ImageIO.read(is);  
  798.             BufferedImage image2=ImageIO.read(is2);  
  799.             Graphics g=image.getGraphics();  
  800.             g.drawImage(image2,0,image.getHeight()/2-image2.getHeight()/2,null);  
  801.             os = new FileOutputStream(toPath);  
  802.             JPEGImageEncoder enc=JPEGCodec.createJPEGEncoder(os);  
  803.             enc.encode(image);  
  804.         }catch(Exception e){  
  805.             e.printStackTrace();  
  806.         }finally{  
  807.             if(os != null){  
  808.                 os.close();  
  809.             }  
  810.             if(is2 != null){  
  811.                 is2.close();  
  812.             }  
  813.             if(is != null){  
  814.                 is.close();  
  815.             }  
  816.         }  
  817.     }  
  818.       
  819.     /** 
  820.      * 将附加图片合并到底图的右边中央 
  821.      * @param negativeImagePath 底图路径 
  822.      * @param additionImagePath 附加图片路径 
  823.      * @param toPath    合成图片写入路径 
  824.      * @throws IOException 
  825.      */  
  826.     public void mergeBothImageRightcenter(String negativeImagePath,String additionImagePath,String toPath ) throws IOException{  
  827.         InputStream is= null;  
  828.         InputStream is2= null;  
  829.         OutputStream os = null;  
  830.         try{  
  831.             is=new FileInputStream(negativeImagePath);  
  832.             is2=new FileInputStream(additionImagePath);  
  833.             BufferedImage image=ImageIO.read(is);  
  834.             BufferedImage image2=ImageIO.read(is2);  
  835.             Graphics g=image.getGraphics();  
  836.             g.drawImage(image2,image.getWidth()-image2.getWidth(),image.getHeight()/2-image2.getHeight()/2,null);  
  837.             os = new FileOutputStream(toPath);  
  838.             JPEGImageEncoder enc=JPEGCodec.createJPEGEncoder(os);  
  839.             enc.encode(image);  
  840.         }catch(Exception e){  
  841.             e.printStackTrace();  
  842.         }finally{  
  843.             if(os != null){  
  844.                 os.close();  
  845.             }  
  846.             if(is2 != null){  
  847.                 is2.close();  
  848.             }  
  849.             if(is != null){  
  850.                 is.close();  
  851.             }  
  852.         }  
  853.     }  
  854.       
  855.     /** 
  856.      * 图片灰化操作 
  857.      * @param srcImage 读取图片路径 
  858.      * @param toPath    写入灰化后的图片路径 
  859.      * @param imageFormat 图片写入格式 
  860.      */   
  861.     public void grayImage(String srcImage,String toPath,String imageFormat){  
  862.         try{  
  863.             BufferedImage src = ImageIO.read(new File(srcImage));  
  864.             ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);  
  865.             ColorConvertOp op = new ColorConvertOp(cs, null);  
  866.             src = op.filter(src, null);  
  867.             ImageIO.write(src, imageFormat, new File(toPath));  
  868.         }catch(Exception e){  
  869.             e.printStackTrace();  
  870.         }  
  871.     }  
  872.       
  873.     /** 
  874.      * 在源图片上设置水印文字 
  875.      * @param srcImagePath  源图片路径 
  876.      * @param alpha 透明度(0<alpha<1) 
  877.      * @param font  字体(例如:宋体) 
  878.      * @param fontStyle     字体格式(例如:普通样式--Font.PLAIN、粗体--Font.BOLD ) 
  879.      * @param fontSize  字体大小 
  880.      * @param color 字体颜色(例如:黑色--Color.BLACK) 
  881.      * @param inputWords        输入显示在图片上的文字 
  882.      * @param x     文字显示起始的x坐标 
  883.      * @param y     文字显示起始的y坐标 
  884.      * @param imageFormat   写入图片格式(png/jpg等) 
  885.      * @param toPath    写入图片路径 
  886.      * @throws IOException  
  887.      */  
  888.     public void alphaWords2Image(String srcImagePath,float alpha,  
  889.             String font,int fontStyle,int fontSize,Color color,  
  890.             String inputWords,int x,int y,String imageFormat,String toPath) throws IOException{  
  891.         FileOutputStream fos=null;  
  892.         try {  
  893.             BufferedImage image = ImageIO.read(new File(srcImagePath));  
  894.             //创建java2D对象   
  895.             Graphics2D g2d=image.createGraphics();  
  896.             //用源图像填充背景   
  897.             g2d.drawImage(image, 00, image.getWidth(), image.getHeight(), nullnull);  
  898.             //设置透明度   
  899.             AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha);  
  900.             g2d.setComposite(ac);  
  901.             //设置文字字体名称、样式、大小   
  902.             g2d.setFont(new Font(font, fontStyle, fontSize));  
  903.             g2d.setColor(color);//设置字体颜色   
  904.             g2d.drawString(inputWords, x, y); //输入水印文字及其起始x、y坐标   
  905.             g2d.dispose();  
  906.             fos=new FileOutputStream(toPath);  
  907.             ImageIO.write(image, imageFormat, fos);  
  908.         } catch (Exception e) {  
  909.            e.printStackTrace();  
  910.         }finally{  
  911.             if(fos!=null){  
  912.                 fos.close();  
  913.             }  
  914.         }  
  915.     }  
  916.       
  917.     /** 
  918.      * 在源图像上设置图片水印   
  919.      *  ---- 当alpha==1时文字不透明(和在图片上直接输入文字效果一样) 
  920.      * @param srcImagePath  源图片路径 
  921.      * @param appendImagePath   水印图片路径 
  922.      * @param alpha 透明度 
  923.      * @param x     水印图片的起始x坐标 
  924.      * @param y     水印图片的起始y坐标 
  925.      * @param width 水印图片的宽度 
  926.      * @param height        水印图片的高度 
  927.      * @param imageFormat   图像写入图片格式 
  928.      * @param toPath    图像写入路径 
  929.      * @throws IOException  
  930.      */  
  931.     public void alphaImage2Image(String srcImagePath,String appendImagePath,  
  932.             float alpha,int x,int y,int width,int height,  
  933.             String imageFormat,String toPath) throws IOException{  
  934.         FileOutputStream fos = null;  
  935.         try {  
  936.             BufferedImage image = ImageIO.read(new File(srcImagePath));  
  937.             //创建java2D对象   
  938.             Graphics2D g2d=image.createGraphics();  
  939.             //用源图像填充背景   
  940.             g2d.drawImage(image, 00, image.getWidth(), image.getHeight(), nullnull);  
  941.             //设置透明度   
  942.             AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha);  
  943.             g2d.setComposite(ac);  
  944.             //设置水印图片的起始x/y坐标、宽度、高度   
  945.             BufferedImage appendImage = ImageIO.read(new File(appendImagePath));  
  946.             g2d.drawImage(appendImage, x, y, width, height, nullnull);  
  947.             g2d.dispose();  
  948.             fos=new FileOutputStream(toPath);  
  949.             ImageIO.write(image, imageFormat, fos);  
  950.         } catch (Exception e) {  
  951.            e.printStackTrace();  
  952.         }finally{  
  953.             if(fos!=null){  
  954.                 fos.close();  
  955.             }  
  956.         }  
  957.     }  
  958.       
  959.     /** 
  960.      * 画单点 ---- 实际上是画一个填充颜色的圆 
  961.      * ---- 以指定点坐标为中心画一个小半径的圆形,并填充其颜色来充当点 
  962.      * @param srcImagePath   源图片颜色 
  963.      * @param x     点的x坐标 
  964.      * @param y     点的y坐标 
  965.      * @param width 填充的宽度 
  966.      * @param height    填充的高度 
  967.      * @param ovalColor 填充颜色 
  968.      * @param imageFormat   写入图片格式 
  969.      * @param toPath    写入路径 
  970.      * @throws IOException 
  971.      */  
  972.     public void drawPoint(String srcImagePath,int x,int y,int width,int height,Color ovalColor,String imageFormat,String toPath) throws IOException{  
  973.         FileOutputStream fos = null;  
  974.         try {  
  975.             //获取源图片   
  976.             BufferedImage image = ImageIO.read(new File(srcImagePath));  
  977.             //根据xy点坐标绘制连接线   
  978.             Graphics2D g2d = image.createGraphics();  
  979.             g2d.setColor(ovalColor);  
  980.             //填充一个椭圆形   
  981.             g2d.fillOval(x, y, width, height);  
  982.             fos = new FileOutputStream(toPath);  
  983.             ImageIO.write(image, imageFormat, fos);   
  984.         } catch (IOException e) {  
  985.             e.printStackTrace();  
  986.         }finally{  
  987.             if(fos!=null){  
  988.                 fos.close();  
  989.             }  
  990.         }  
  991.     }  
  992.       
  993.     /** 
  994.      * 画一组(多个)点---- 实际上是画一组(多个)填充颜色的圆 
  995.      * ---- 以指定点坐标为中心画一个小半径的圆形,并填充其颜色来充当点 
  996.      * @param srcImagePath  原图片路径 
  997.      * @param pointList 点列表 
  998.      * @param width 宽度 
  999.      * @param height        高度 
  1000.      * @param ovalColor 填充颜色 
  1001.      * @param imageFormat   写入图片颜色 
  1002.      * @param toPath    写入路径 
  1003.      * @throws IOException 
  1004.      */  
  1005.     public void drawPoints(String srcImagePath,List pointList,int width,int height,Color ovalColor,String imageFormat,String toPath) throws IOException{  
  1006.         FileOutputStream fos = null;  
  1007.         try {  
  1008.             //获取源图片   
  1009.             BufferedImage image = ImageIO.read(new File(srcImagePath));  
  1010.             //根据xy点坐标绘制连接线   
  1011.             Graphics2D g2d = image.createGraphics();  
  1012.             g2d.setColor(ovalColor);  
  1013.             //填充一个椭圆形   
  1014.             if(pointList != null){  
  1015.                 for(int i=0;i<pointList.size();i++){  
  1016.                     Point point = (Point)pointList.get(i);  
  1017.                     int x = (int) point.getX();  
  1018.                     int y = (int) point.getY();  
  1019.                     g2d.fillOval(x, y, width, height);  
  1020.                 }  
  1021.             }  
  1022.             fos = new FileOutputStream(toPath);  
  1023.             ImageIO.write(image, imageFormat, fos);   
  1024.         } catch (IOException e) {  
  1025.             e.printStackTrace();  
  1026.         }finally{  
  1027.             if(fos!=null){  
  1028.                 fos.close();  
  1029.             }  
  1030.         }  
  1031.     }  
  1032.       
  1033.     /** 
  1034.      * 画线段 
  1035.      * @param srcImagePath  源图片路径 
  1036.      * @param x1    第一个点x坐标 
  1037.      * @param y1    第一个点y坐标 
  1038.      * @param x2    第二个点x坐标 
  1039.      * @param y2    第二个点y坐标 
  1040.      * @param lineColor 线条颜色 
  1041.      * @param toPath    图像写入路径 
  1042.      * @param imageFormat   图像写入格式 
  1043.      * @throws IOException   
  1044.      */  
  1045.     public void drawLine(String srcImagePath,int x1,int y1,int x2,int y2, Color lineColor,String toPath,String imageFormat) throws IOException{  
  1046.         FileOutputStream fos = null;  
  1047.         try {  
  1048.             //获取源图片   
  1049.             BufferedImage image = ImageIO.read(new File(srcImagePath));  
  1050.             //根据xy点坐标绘制连接线   
  1051.             Graphics2D g2d = image.createGraphics();  
  1052.             g2d.setColor(lineColor);  
  1053.             g2d.drawLine( x1, y1, x2, y2);  
  1054.             fos = new FileOutputStream(toPath);  
  1055.             ImageIO.write(image, imageFormat, fos);   
  1056.         } catch (IOException e) {  
  1057.             e.printStackTrace();  
  1058.         }finally{  
  1059.             if(fos!=null){  
  1060.                 fos.close();  
  1061.             }  
  1062.         }  
  1063.     }  
  1064.       
  1065.     /** 
  1066.      * 画折线 / 线段 
  1067.      * ---- 2个点即画线段,多个点画折线 
  1068.      * @param srcImagePath  源图片路径 
  1069.      * @param xPoints   x坐标数组 
  1070.      * @param yPoints   y坐标数组 
  1071.      * @param nPoints   点的数量 
  1072.      * @param lineColor 线条颜色 
  1073.      * @param toPath    图像写入路径 
  1074.      * @param imageFormat   图片写入格式 
  1075.      * @throws IOException   
  1076.      */  
  1077.     public void drawPolyline(String srcImagePath,int[] xPoints, int[] yPoints, int nPoints,Color lineColor,String toPath,String imageFormat) throws IOException{  
  1078.         FileOutputStream fos = null;  
  1079.         try {  
  1080.             //获取源图片   
  1081.             BufferedImage image = ImageIO.read(new File(srcImagePath));  
  1082.             //根据xy点坐标绘制连接线   
  1083.             Graphics2D g2d = image.createGraphics();  
  1084.             //设置线条颜色   
  1085.             g2d.setColor(lineColor);  
  1086.             g2d.drawPolyline(xPoints, yPoints, nPoints);  
  1087.             //图像写出路径   
  1088.             fos = new FileOutputStream(toPath);  
  1089.             ImageIO.write(image, imageFormat, fos);   
  1090.         } catch (IOException e) {  
  1091.             e.printStackTrace();  
  1092.         }finally{  
  1093.             if(fos!=null){  
  1094.                 fos.close();  
  1095.             }  
  1096.         }  
  1097.     }  
  1098.       
  1099.     /** 
  1100.      * 绘制折线,并突出显示转折点 
  1101.      * @param srcImagePath  源图片路径 
  1102.      * @param xPoints   x坐标数组 
  1103.      * @param yPoints   y坐标数组 
  1104.      * @param nPoints   点的数量 
  1105.      * @param lineColor 连线颜色 
  1106.      * @param width 点的宽度 
  1107.      * @param height        点的高度 
  1108.      * @param ovalColor 点的填充颜色 
  1109.      * @param toPath    图像写入路径 
  1110.      * @param imageFormat   图像写入格式 
  1111.      * @throws IOException 
  1112.      */  
  1113.     public void drawPolylineShowPoints(String srcImagePath,int[] xPoints, int[] yPoints, int nPoints,Color lineColor,int width,int height,Color ovalColor,String toPath,String imageFormat) throws IOException{  
  1114.         FileOutputStream fos = null;  
  1115.         try {  
  1116.             //获取源图片   
  1117.             BufferedImage image = ImageIO.read(new File(srcImagePath));  
  1118.             //根据xy点坐标绘制连接线   
  1119.             Graphics2D g2d = image.createGraphics();  
  1120.             //设置线条颜色   
  1121.             g2d.setColor(lineColor);  
  1122.             //画线条   
  1123.             g2d.drawPolyline(xPoints, yPoints, nPoints);  
  1124.             //设置圆点颜色   
  1125.             g2d.setColor(ovalColor);  
  1126.             //画圆点   
  1127.             if(xPoints != null){  
  1128.                 for(int i=0;i<xPoints.length;i++){  
  1129.                     int x = xPoints[i];  
  1130.                     int y = yPoints[i];  
  1131.                     g2d.fillOval(x, y, width, height);  
  1132.                 }  
  1133.             }  
  1134.             //图像写出路径   
  1135.             fos = new FileOutputStream(toPath);  
  1136.             ImageIO.write(image, imageFormat, fos);   
  1137.         } catch (IOException e) {  
  1138.             e.printStackTrace();  
  1139.         }finally{  
  1140.             if(fos!=null){  
  1141.                 fos.close();  
  1142.             }  
  1143.         }  
  1144.     }  
  1145.       
  1146.       
  1147.     /**  
  1148.      * 绘制一个由 x 和 y 坐标数组定义的闭合多边形 
  1149.      * @param srcImagePath 源图片路径 
  1150.      * @param xPoints   x坐标数组 
  1151.      * @param yPoints   y坐标数组 
  1152.      * @param nPoints   坐标点的个数 
  1153.      * @param polygonColor  线条颜色 
  1154.      * @param imageFormat   图像写入格式 
  1155.      * @param toPath    图像写入路径 
  1156.      * @throws IOException  
  1157.      */  
  1158.     public void drawPolygon(String srcImagePath,int[] xPoints,int[] yPoints,int nPoints,Color polygonColor,String imageFormat,String toPath) throws IOException {  
  1159.         FileOutputStream fos = null;  
  1160.         try {  
  1161.             //获取图片   
  1162.             BufferedImage image = ImageIO.read(new File(srcImagePath));  
  1163.             //根据xy点坐标绘制闭合多边形   
  1164.             Graphics2D g2d = image.createGraphics();  
  1165.             g2d.setColor(polygonColor);  
  1166.             g2d.drawPolygon(xPoints, yPoints, nPoints);  
  1167.             fos = new FileOutputStream(toPath);  
  1168.             ImageIO.write(image, imageFormat, fos);   
  1169.             g2d.dispose();  
  1170.         } catch (Exception e) {  
  1171.             e.printStackTrace();  
  1172.         }finally{  
  1173.                     if(fos!=null){  
  1174.                         fos.close();  
  1175.                     }   
  1176.             }  
  1177.     }  
  1178.       
  1179.     /** 
  1180.      * 绘制并填充多边形 
  1181.      * @param srcImagePath  源图像路径 
  1182.      * @param xPoints   x坐标数组 
  1183.      * @param yPoints   y坐标数组 
  1184.      * @param nPoints   坐标点个数 
  1185.      * @param polygonColor  多边形填充颜色 
  1186.      * @param alpha 多边形部分透明度 
  1187.      * @param imageFormat   写入图形格式 
  1188.      * @param toPath    写入图形路径 
  1189.      * @throws IOException 
  1190.      */  
  1191.     public void drawAndAlphaPolygon(String srcImagePath,int[] xPoints,int[] yPoints,int nPoints,Color polygonColor,float alpha,String imageFormat,String toPath) throws IOException{  
  1192.         FileOutputStream fos = null;  
  1193.         try {  
  1194.             //获取图片   
  1195.             BufferedImage image = ImageIO.read(new File(srcImagePath));  
  1196.             //根据xy点坐标绘制闭合多边形   
  1197.             Graphics2D g2d = image.createGraphics();  
  1198.             g2d.setColor(polygonColor);  
  1199.             //设置透明度   
  1200.             AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha);  
  1201.             g2d.setComposite(ac);  
  1202.             g2d.fillPolygon(xPoints, yPoints, nPoints);  
  1203.             fos = new FileOutputStream(toPath);  
  1204.             ImageIO.write(image, imageFormat, fos);   
  1205.             g2d.dispose();  
  1206.         } catch (Exception e) {  
  1207.             e.printStackTrace();  
  1208.         }finally{  
  1209.                     if(fos!=null){  
  1210.                         fos.close();  
  1211.                     }   
  1212.             }  
  1213.     }  
  1214.       
  1215.       
  1216.     public static void main(String[] args)throws Exception{  
  1217.         OperateImage imageObj = new OperateImage();  
  1218.           
  1219.         /*String srcPath = "D:/test/fileSource/004.jpg"; 
  1220.         String toPath = "D:/test/desk/+e004.jpg"; 
  1221.         int x = 200; 
  1222.         int y = 300; 
  1223.         int width = 300; 
  1224.         int height = 200 ; 
  1225.         String readImageFormat = "jpg"; 
  1226.         String writeImageFormat = "jpg"*/;  
  1227.         //imageObj.cropImage(srcPath, toPath, x, y, width, height,readImageFormat,writeImageFormat);//剪切图片   
  1228.         //imageObj.resizeImage(srcPath, toPath, 400, 400);//按指定的长宽重置图形大小   
  1229.        //imageObj.reduceImageByRatio(srcPath, toPath, 3, 3);//按指定长和宽的比例缩小图形   
  1230.        //imageObj.enlargementImageByRatio(srcPath, toPath, 2, 2);//按指定长和宽的比例放大图形   
  1231.        //imageObj.reduceImageEqualProportion(srcPath, toPath, 4);//长高等比例缩小   
  1232.         //imageObj.enlargementImageEqualProportion(srcPath, toPath, 2);//长高等比例放大   
  1233.        /* String negativeImagePath = "D:/test/fileSource/004.jpg"; 
  1234.         String additionImagePath = "D:/test/fileSource/005.jpg"; 
  1235.         int x = 200; 
  1236.         int y = 200; 
  1237.         String toPath = "D:/test/desk/004+005-rightcenter.jpg";*/  
  1238.         //imageObj.mergeBothImage(negativeImagePath, additionImagePath, x, y, toPath); //按指定坐标合并图片   
  1239.         //imageObj.mergeBothImageTopleftcorner(negativeImagePath, additionImagePath, toPath);//合并到左上角   
  1240.         //imageObj.mergeBothImageToprightcorner(negativeImagePath, additionImagePath, toPath);//合并到右上角   
  1241.         //imageObj.mergeBothImageLeftbottom(negativeImagePath, additionImagePath, toPath);//合并到左下角   
  1242.         //imageObj.mergeBothImageRightbottom(negativeImagePath, additionImagePath, toPath);//合并到右下角   
  1243.         //imageObj.mergeBothImageCenter(negativeImagePath, additionImagePath, toPath);//合并到正中央   
  1244.         //imageObj.mergeBothImageTopcenter(negativeImagePath, additionImagePath, toPath);//合并到上边中央   
  1245.         //imageObj.mergeBothImageBottomcenter(negativeImagePath, additionImagePath, toPath);//合并到下边中央   
  1246.         //imageObj.mergeBothImageLeftcenter(negativeImagePath, additionImagePath, toPath);//合并到左边中央   
  1247.         //imageObj.mergeBothImageRightcenter(negativeImagePath, additionImagePath, toPath);//合并到右边中央   
  1248.           
  1249.         /* 
  1250.         String srcImage = "D:/test/fileSource/001.jpg"; 
  1251.         String toPath = "D:/test/desk/001-gray.jpg"; 
  1252.         String imageFormat = "jpg"; 
  1253.         imageObj.grayImage(srcImage, toPath, imageFormat);//图片灰化 
  1254.          */      
  1255.           
  1256.         /* 
  1257.         String firstSrcImagePath = "D:/test/desk/003.jpg"; 
  1258.         String secondSrcImagePath = "D:/test/desk/004.jpg"; 
  1259.         String imageFormat = "jpg"; 
  1260.         String toPath = "D:/test/desk/003-004-join.jpg"; 
  1261.         imageObj.joinImagesHorizontal(firstSrcImagePath, secondSrcImagePath, imageFormat, toPath);//横向拼接图片 
  1262.         */  
  1263.           
  1264.         /* 
  1265.         String firstSrcImagePath = "D:/test/desk/001-002-join.jpg"; 
  1266.         String secondSrcImagePath = "D:/test/desk/003-004-join.jpg"; 
  1267.         String imageFormat = "jpg"; 
  1268.         String toPath = "D:/test/desk/all-join.jpg"; 
  1269.         imageObj.joinImagesVertical(firstSrcImagePath, secondSrcImagePath, imageFormat, toPath);//纵向拼接图片 
  1270.         */  
  1271.           
  1272.         /*String srcImagePath = "D:/test/fileSource/002.jpg"; 
  1273.         int[] xPoints = {20,100,160,270,500};  
  1274.         int[] yPoints = {30,150,172,295,615}; 
  1275.         int nPoints = 5;  
  1276.         String toPath = "D:/test/desk/polygon-002.png"; 
  1277.         imageObj.drawPolygon(srcImagePath, xPoints, yPoints, nPoints, Color.MAGENTA, "jpg", toPath); //根据坐标数组绘制多边形 
  1278.         */  
  1279.   
  1280.         /*String srcImagePath = "D:/test/fileSource/004.jpg"; 
  1281.         String appendImagePath = "D:/test/fileSource/005.jpg"; 
  1282.         float alpha = 0.2F; 
  1283.         String  font = "宋体"; 
  1284.         int fontStyle = Font.PLAIN; 
  1285.         int fontSize = 32; 
  1286.         Color color = Color.RED; 
  1287.         String inputWords = "图片上设置水印文字 ---- 宋体 普通字体 32号字 红色 透明度0.5"; 
  1288.         int x = 20; 
  1289.         int y = 40; 
  1290.         String imageFormat = "jpg"; 
  1291.         String toPath = "D:/test/desk/alphaI2I-001.png";*/  
  1292.         //imageObj.alphaWords2Image(srcImagePath, alpha, font, fontStyle, fontSize, color, inputWords, x, y, imageFormat, toPath); //设置文字水印   
  1293.         //imageObj.alphaImage2Image(srcImagePath, appendImagePath, alpha, x, y, 300, 200, imageFormat, toPath);//设置图片水印   
  1294.           
  1295.         /* 
  1296.         String srcImagePath = "D:/test/fileSource/003.jpg"; 
  1297.         int[] xPoints = {100,150,200,240,300}; 
  1298.         int[] yPoints = {200,60,280,160,100}; 
  1299.         int nPoints = 5; 
  1300.         Color lineColor = Color.RED; 
  1301.         String toPath = "D:/test/desk/polyline-003.jpg"; 
  1302.         String imageFormat = "jpg"; 
  1303.         imageObj.drawPolyline(srcImagePath, xPoints, yPoints, nPoints, lineColor,toPath, imageFormat);//画折线 
  1304.          */       
  1305.           
  1306.         /* 
  1307.         int x1 = 50; 
  1308.         int y1 = 100; 
  1309.         int x2 = 600; 
  1310.         int y2 = 150; 
  1311.         Color lineColor = Color.BLUE; 
  1312.         imageObj.drawLine(srcImagePath, x1, y1, x2, y2, lineColor,toPath, imageFormat);//画线段 
  1313.          */       
  1314.           
  1315.         /* 
  1316.         String srcImagePath = "D:/test/fileSource/002.jpg"; 
  1317.         int x = 400; 
  1318.         int y = 500; 
  1319.         int width = 10; 
  1320.         int height = 10; 
  1321.         Color ovalColor = Color.RED; 
  1322.         String imageFormat = "jpg"; 
  1323.         String toPath = "D:/test/desk/point-002.jpg"; 
  1324.         imageObj.drawPoint(srcImagePath, x, y, width, height, ovalColor, imageFormat, toPath);//画一个圆点 
  1325.         */  
  1326.           
  1327.         /*List pointList = new ArrayList(); 
  1328.         Point p1 = new Point(60,80); 
  1329.         pointList.add(p1); 
  1330.         Point p2 = new Point(160,80); 
  1331.         pointList.add(p2); 
  1332.         Point p3 = new Point(60,180); 
  1333.         pointList.add(p3); 
  1334.         Point p4 = new Point(260,180); 
  1335.         pointList.add(p4); 
  1336.         Point p5 = new Point(460,380); 
  1337.         pointList.add(p5); 
  1338.         String srcImagePath = "D:/test/fileSource/004.jpg"; 
  1339.         int width = 10; 
  1340.         int height = 10; 
  1341.         Color ovalColor = Color.RED; 
  1342.         String imageFormat = "jpg"; 
  1343.         String toPath = "D:/test/desk/points-004.jpg"; 
  1344.         imageObj.drawPoints(srcImagePath, pointList, width, height, ovalColor, imageFormat, toPath);//画出一组(多个)点 
  1345.          */     
  1346.           
  1347.         /* 
  1348.         int[] xPoints = {50,100,180,400,600}; 
  1349.         int[] yPoints = {200,100,160,300,640}; 
  1350.         int nPoints = 5; 
  1351.         Color lineColor = Color.PINK; 
  1352.         String srcImagePath = "D:/test/fileSource/003.jpg"; 
  1353.         String toPath = "D:/test/desk/showpoints-003.jpg"; 
  1354.         imageObj.drawPolylineShowPoints(srcImagePath, xPoints, yPoints, nPoints, lineColor, width, height, ovalColor, toPath, imageFormat);//画折线并突出显示点 
  1355.          */     
  1356.           
  1357.         /* 
  1358.         String srcImagePath ="D:/test/fileSource/004.jpg";  
  1359.         int[] xPoints ={50,90,180,320,640}; 
  1360.         int[] yPoints ={200,300,120,240,360}; 
  1361.         int nPoints = 5; 
  1362.         Color polygonColor = Color.PINK; 
  1363.         float alpha = (float) 0.2; 
  1364.         String imageFormat ="jpg"; 
  1365.         String toPath ="D:/test/desk/drawalpha-004.jpg"; 
  1366.         imageObj.drawAndAlphaPolygon(srcImagePath, xPoints, yPoints, nPoints, polygonColor, alpha, imageFormat, toPath); 
  1367.         */  
  1368.         /* 
  1369.         String negativeImagePath = "D:/test/fileSource/001.jpg"; 
  1370.         String additionImagePath = "D:/test/fileSource/006.png"; 
  1371.         String  toPath = "D:/test/fileSource/001.jpg"; 
  1372.         long start = System.currentTimeMillis(); 
  1373.         for(int i=0;i<1000;i++){ 
  1374.             Random rand = new Random(); 
  1375.             int x = rand.nextInt(1024); 
  1376.             int y =  rand.nextInt(768); 
  1377.             imageObj.mergeBothImage(negativeImagePath, additionImagePath, x, y, toPath);//每次附加合并一张图片(循环若干次) 
  1378.         } 
  1379.         long end = System.currentTimeMillis(); 
  1380.         System.out.println(end-start);*/  
  1381.         //100 -- 45844   
  1382.         //1000 -- 411156   
  1383.         /*改进思路:将mergeBothImage方法 修改为mergeImageList方法, 
  1384.         通过将图片的坐标点装入list容器,然后再取出一来在方法中一次性与图片合并, 
  1385.         不再每次都打开底图、保存合成图片,关闭流*/  
  1386.   
  1387.         //叠加组合图像   
  1388.         /*String negativeImagePath = "D:/test/fileSource/001.jpg"; 
  1389.         String  toPath = "D:/test/fileSource/001.jpg"; 
  1390.         String additionImagePath = "D:/test/fileSource/007.png"; 
  1391.         List additionImageList = new ArrayList(); 
  1392.         int count = 0; 
  1393.         for(int i=0;i<100;i++){//为什么总是连续生成一样的随机数??? 
  1394.             Random rand = new Random(); 
  1395.             int x = rand.nextInt(1020); 
  1396.             String xStr = x+""; 
  1397.             int y =  rand.nextInt(760); 
  1398.             String yStr = y +""; 
  1399.             String[] str = {xStr,yStr,additionImagePath}; 
  1400.             additionImageList.add(str); 
  1401.             count++; 
  1402.             //System.out.println(xStr+"   :     "+yStr); 
  1403.         } 
  1404.         System.out.println(count); 
  1405.         long start = System.currentTimeMillis(); 
  1406.         imageObj.mergeImageList(negativeImagePath, additionImageList,"jpg", toPath); 
  1407.         long end = System.currentTimeMillis(); 
  1408.         System.out.println(end-start);*/  
  1409.         //                                第一次        第二次      第三次   
  1410.         //100张耗时(毫秒)        --2003          1792            1869           1747         1871            1793   
  1411.         //1000张耗时(毫秒)   --15334         15200       15236         15903         16028       15545   
  1412.         //10000张耗时(毫秒)  --153010        153340      152673       154978         156506      154854                                  
  1413.         //如果list.size()<=100,则调用此方法,   
  1414.         //如果list.size()>100,则调用Jmagick的方法。   
  1415.           
  1416.         /*List iamgePathList = new ArrayList();     // D:/test/16a/ 
  1417.         iamgePathList.add("D:/test/16a/12384_2492.jpg"); 
  1418.         iamgePathList.add("D:/test/16a/12384_2493.jpg"); 
  1419.         iamgePathList.add("D:/test/16a/12384_2494.jpg"); 
  1420.         iamgePathList.add("D:/test/16a/12384_2495.jpg"); 
  1421.         iamgePathList.add("D:/test/16a/12384_2496.jpg"); 
  1422.         iamgePathList.add("D:/test/16a/12384_2497.jpg"); 
  1423.         iamgePathList.add("D:/test/16a/12384_2498.jpg"); 
  1424.         iamgePathList.add("D:/test/16a/12384_2499.jpg"); 
  1425.         iamgePathList.add("D:/test/16a/12384_2500.jpg"); 
  1426.         iamgePathList.add("D:/test/16a/12384_2501.jpg"); 
  1427.         iamgePathList.add("D:/test/16a/12384_2502.jpg");*/  
  1428.         //String imageFormat = "jpg";   
  1429.         //String toPath = "D:/test/desk/16a_v1.jpg";   
  1430.         //imageObj.joinImageListHorizontal(iamgePathList, imageFormat, toPath);   
  1431.           
  1432.         /*String imageFormat = "jpg"; 
  1433.         String[] pics1 = {"D:/test/16a/12384_2502.jpg","D:/test/16a/12384_2501.jpg", 
  1434.                 "D:/test/16a/12384_2500.jpg","D:/test/16a/12384_2499.jpg","D:/test/16a/12384_2498.jpg", 
  1435.                 "D:/test/16a/12384_2497.jpg","D:/test/16a/12384_2496.jpg","D:/test/16a/12384_2495.jpg", 
  1436.                 "D:/test/16a/12384_2494.jpg","D:/test/16a/12384_2493.jpg","D:/test/16a/12384_2492.jpg"}; 
  1437.          
  1438.         String[] pics2 = {"D:/test/16a/12385_2502.jpg","D:/test/16a/12385_2501.jpg", 
  1439.                 "D:/test/16a/12385_2500.jpg","D:/test/16a/12385_2499.jpg","D:/test/16a/12385_2498.jpg", 
  1440.                 "D:/test/16a/12385_2497.jpg","D:/test/16a/12385_2496.jpg","D:/test/16a/12385_2495.jpg", 
  1441.                 "D:/test/16a/12385_2494.jpg","D:/test/16a/12385_2493.jpg","D:/test/16a/12385_2492.jpg"}; 
  1442.          
  1443.         String[] pics3 = {"D:/test/16a/12386_2502.jpg","D:/test/16a/12386_2501.jpg", 
  1444.                 "D:/test/16a/12386_2500.jpg","D:/test/16a/12386_2499.jpg","D:/test/16a/12386_2498.jpg", 
  1445.                 "D:/test/16a/12386_2497.jpg","D:/test/16a/12386_2496.jpg","D:/test/16a/12386_2495.jpg", 
  1446.                 "D:/test/16a/12386_2494.jpg","D:/test/16a/12386_2493.jpg","D:/test/16a/12386_2492.jpg"}; 
  1447.          
  1448.         String[] pics4 = {"D:/test/16a/12387_2502.jpg","D:/test/16a/12387_2501.jpg", 
  1449.                 "D:/test/16a/12387_2500.jpg","D:/test/16a/12387_2499.jpg","D:/test/16a/12387_2498.jpg", 
  1450.                 "D:/test/16a/12387_2497.jpg","D:/test/16a/12387_2496.jpg","D:/test/16a/12387_2495.jpg", 
  1451.                 "D:/test/16a/12387_2494.jpg","D:/test/16a/12387_2493.jpg","D:/test/16a/12387_2492.jpg"}; 
  1452.          
  1453.         String[] pics5 = {"D:/test/16a/12388_2502.jpg","D:/test/16a/12388_2501.jpg", 
  1454.                 "D:/test/16a/12388_2500.jpg","D:/test/16a/12388_2499.jpg","D:/test/16a/12388_2498.jpg", 
  1455.                 "D:/test/16a/12388_2497.jpg","D:/test/16a/12388_2496.jpg","D:/test/16a/12388_2495.jpg", 
  1456.                 "D:/test/16a/12388_2494.jpg","D:/test/16a/12388_2493.jpg","D:/test/16a/12388_2492.jpg"}; 
  1457.          
  1458.         String[] pics6 = {"D:/test/16a/12389_2502.jpg","D:/test/16a/12389_2501.jpg", 
  1459.                 "D:/test/16a/12389_2500.jpg","D:/test/16a/12389_2499.jpg","D:/test/16a/12389_2498.jpg", 
  1460.                 "D:/test/16a/12389_2497.jpg","D:/test/16a/12389_2496.jpg","D:/test/16a/12389_2495.jpg", 
  1461.                 "D:/test/16a/12389_2494.jpg","D:/test/16a/12389_2493.jpg","D:/test/16a/12389_2492.jpg"}; 
  1462.          
  1463.         String toPath1 = "D:/test/desk/16a_v1.jpg"; 
  1464.         String toPath2 = "D:/test/desk/16a_v2.jpg"; 
  1465.         String toPath3 = "D:/test/desk/16a_v3.jpg"; 
  1466.         String toPath4 = "D:/test/desk/16a_v4.jpg"; 
  1467.         String toPath5 = "D:/test/desk/16a_v5.jpg"; 
  1468.         String toPath6 = "D:/test/desk/16a_v6.jpg"; 
  1469.          
  1470.         String[] pics7 = {toPath1,toPath2,toPath3,toPath4,toPath5,toPath6}; 
  1471.         String toPath7 = "D:/test/desk/16a_h1.jpg"; 
  1472.          
  1473.         long start = System.currentTimeMillis(); 
  1474.         imageObj.joinImageListVertical(pics1, imageFormat, toPath1); 
  1475.         imageObj.joinImageListVertical(pics2, imageFormat, toPath2); 
  1476.         imageObj.joinImageListVertical(pics3, imageFormat, toPath3); 
  1477.         imageObj.joinImageListVertical(pics4, imageFormat, toPath4); 
  1478.         imageObj.joinImageListVertical(pics5, imageFormat, toPath5); 
  1479.         imageObj.joinImageListVertical(pics6, imageFormat, toPath6); 
  1480.          
  1481.         imageObj.joinImageListHorizontal(pics7, imageFormat, toPath7); 
  1482.         long end = System.currentTimeMillis(); 
  1483.         System.out.println(end-start);*/  
  1484.           
  1485.         String str = "北京\n上海\n广州\n深圳";  
  1486.         System.out.println(str);  
  1487.         String path = "c:/relevantdata.txt";  
  1488.         FileOutputStream fops = new FileOutputStream(path);  
  1489.         fops.write(str.getBytes());  
  1490.           
  1491.         BufferedReader inputStream = new BufferedReader(new FileReader(new File(path)));  
  1492.         String mrMsg = "";  
  1493.         while((mrMsg = inputStream.readLine())!=null){  
  1494.         System.out.println(mrMsg);  
  1495.         }  
  1496.         }  
  1497.         //数量        11          11x6   
  1498.         //纵向        375        
  1499.         //横向        391     3250   
  1500. }  
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭