首页 > 技术文章 > 图片处理

xiatc 2020-07-09 13:07 原文

package czc.superzig.modular.utils;


import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;

import java.awt.*;
import java.awt.geom.Path2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;

/**
 * @program: superzig-function    c
 * @description:
 * @author: Mr.L
 * @create: 2019-04-25 19:45
 * 抠图 
 **/
public class ImgUtil {
    private static final String SEPARATOR=File.separator;
  //根据 x y w h 第一点的坐标矩形的宽度 和长
  
  public static String readUsingImageReader(String imgUrl, Integer x, Integer y, Integer width, Integer heigth) {
        String pathUrl = SEPARATOR +"home"+SEPARATOR + SEPARATOR + "tupian";
        File file = new File(pathUrl);
        if (!file.exists()){
            file.mkdirs();
        }
        String path=pathUrl+SEPARATOR+ IdUtil.simpleUUID() + ".jpg";
        try {
            Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("jpg");
            ImageReader reader =readers.next();
            InputStream source = new FileInputStream(imgUrl);
            ImageInputStream iis = ImageIO.createImageInputStream(source);
            reader.setInput(iis, true);
            ImageReadParam param = reader.getDefaultReadParam();
            //100,200是左上起始位置,300就是取宽度为300的,就是从100开始取300宽,就是横向100~400,同理纵向200~350的区域就取高度150
            Rectangle rect = new Rectangle(x, y, width, heigth);
            param.setSourceRegion(rect);
            BufferedImage bi = reader.read(0, param);
            ImageIO.write(bi, "jpg", new File(path));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return path;
    }
    
    
    public static String readUsingImageReader(String imgUrl, Integer point0x,Integer point0y,Integer point1x,Integer point1y,Integer point2x,Integer point2y,Integer point3x,Integer point3y) throws IOException {
    	//计算矩形的长和宽
    	Integer width=(int) Math.pow(Math.pow(point0x-point1x, 2)+Math.pow(point0y-point1y, 2), 0.5);
    	Integer heigth=(int) Math.pow(Math.pow(point1x-point2x, 2)+Math.pow(point1y-point2y, 2), 0.5);
    	BigDecimal y=new BigDecimal(point1y-point0y);
    	BigDecimal x=new BigDecimal(point1x-point0x);
    	
    	//旋转图片
        File ecgFile = new File(imgUrl);
        BufferedImage ecgImage = ImageIO.read(ecgFile);
        double degree=new BigDecimal(90).multiply(y.abs().divide(x.abs().add(y.abs()))).setScale(3).doubleValue();
        BigDecimal bigZero=new BigDecimal(0);
        x=(x.compareTo(bigZero)==0?bigZero:x);
        y=(y.compareTo(bigZero)==0?bigZero:y);
        degree=(x.multiply(y)).compareTo(bigZero)>0?-degree:degree;
        ecgImage=rotateImage(ecgImage, degree,point0x,point0y,0.5);
        ImageIO.write(ecgImage, "jpg", ecgFile);
        String path=readUsingImageReader(imgUrl, (int)(point0x*0.5), (int)(point0y*0.5), (int)(width*0.5), (int)(heigth*0.5));
        //反向旋转图片
        //ecgImage=rotateImage(ecgImage, -1*degree);
    	return path;
    }
    
    
    /**
     *根据坐标点切割图形
     *
     * @author Administrator
     * @Param imgUrl需要切割的图片
     * @Param List<Point> 点列表
     */
    public static String readUsingImageReader(String imgUrl,java.util.List<Point> pointList) throws IOException {
    	if(StrUtil.isBlank(imgUrl)){
    		throw new NullPointerException();
    	}
    	java.util.List<Point> socPointList=new ArrayList<>(pointList);
    	//设置图片导出路径
    	 String pathUrl = SEPARATOR +"home"+SEPARATOR + SEPARATOR + "tupian";
         //String pathUrl=separator+"image";
         File file = new File(pathUrl);
         if (!file.exists()){
             file.mkdirs();
         }
         String path=pathUrl+SEPARATOR+ IdUtil.simpleUUID() + ".jpg";
         
         //找到最大坐标
         Collections.sort(pointList, new Comparator<Point>(){
        	 @Override
             public int compare(Point p1, Point p2) {
                 //排序属性
                 if(p1.getXCoordinate() <=p2.getXCoordinate()){
                     return 1;
                 }
                 return -1;
             }
         });
         Integer maxXcoordinate=pointList.get(0).getXCoordinate();
         Integer minXcoordinate=pointList.get(pointList.size()-1).getXCoordinate();
         Collections.sort(pointList, new Comparator<Point>(){
        	 @Override
             public int compare(Point p1, Point p2) {
                 //排序属性
                 if(p1.getYCoordinate() <=p2.getYCoordinate()){
                     return 1;
                 }
                 return -1;
             }
         });
         Integer maxYcoordinate=pointList.get(0).getYCoordinate();
         Integer minYcoordinate=pointList.get(pointList.size()-1).getYCoordinate();
         BufferedImage bufferedimage=ImageIO.read(new File(imgUrl));
// 		int w = bufferedimage.getWidth();// 得到图片宽度。
// 		int h = bufferedimage.getHeight();// 得到图片高度。
 		//int type = bufferedimage.getColorModel().getTransparency();// 得到图片透明度。
 		BufferedImage img;// 空的图片。
 		Graphics2D graphics2d;// 空的画笔。
 		(graphics2d = (img = new BufferedImage(maxXcoordinate, maxYcoordinate, BufferedImage.TYPE_INT_RGB))
 		.createGraphics()).setRenderingHint(
 		RenderingHints.KEY_INTERPOLATION,
 		RenderingHints.VALUE_INTERPOLATION_BILINEAR);
 		//创建一个path
 		//设置背景色
 		graphics2d.setBackground(Color.white);
 		graphics2d.clearRect(0, 0, maxXcoordinate, maxYcoordinate);
 		Path2D outline=new Path2D.Double();
 		for(int p=0;p<socPointList.size();p++){
 			Point point=socPointList.get(p);
 			if(p==0){
 				outline.moveTo(point.getXCoordinate(), point.getYCoordinate());
 			}else{
 				outline.lineTo(point.getXCoordinate(), point.getYCoordinate());
 			}
 		}
 		//收尾闭合
 		outline.closePath();  
 		graphics2d.clip(outline);
 		// 从bufferedimagecopy图片至img,0,0是img的坐标。
 		graphics2d.drawImage(bufferedimage,0,0,null);
 		// 空的图片。
 		BufferedImage img1;
 		// 空的画笔。
 		Graphics2D graphics2d1;
 		(graphics2d1 = (img1 = new BufferedImage(maxXcoordinate-minXcoordinate,maxYcoordinate-minYcoordinate, BufferedImage.TYPE_INT_RGB))
 		.createGraphics()).setRenderingHint(
 		RenderingHints.KEY_INTERPOLATION,
 		RenderingHints.VALUE_INTERPOLATION_BILINEAR);
 		// 从bufferedimagecopy图片至img,0,0是img的坐标。
 		graphics2d1.drawImage(img,0,0,maxXcoordinate-minXcoordinate,maxYcoordinate-minYcoordinate,minXcoordinate,minYcoordinate,maxXcoordinate,maxYcoordinate,null);
 		graphics2d1.dispose();
 		ImageIO.write(img1, "jpg", new File(path));
 		return path;
    }
    
    /**
     *旋转图片
     *
     */
    public static BufferedImage rotateImage( BufferedImage bufferedimage, double degree,int x,int y,double scale) {
		int w = bufferedimage.getWidth();
		int h = bufferedimage.getHeight();
		int type = bufferedimage.getColorModel().getTransparency();
		BufferedImage img;// 空的图片。
		Graphics2D graphics2d;// 空的画笔。
		(graphics2d = (img = new BufferedImage(w, h, type))
		.createGraphics()).setRenderingHint(
		RenderingHints.KEY_INTERPOLATION,
		RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		graphics2d.scale(scale, scale);
		// 旋转,degree是整型,度数,比如垂直90度。
		graphics2d.rotate(Math.toRadians(degree), x, y);
		// 从bufferedimagecopy图片至img,0,0是img的坐标。
		graphics2d.drawImage(bufferedimage,0,0, null);
		graphics2d.dispose();
		return img;
	}


    public static int angle(int x1,int y1,int x2,int y2){ 
    	int angle = 0; 
    	int x=Math.abs(x1-x2); 
    	int y=Math.abs(y1-y2); 
    	double z=Math.sqrt(x*x+y*y); 
    	//最终角度 
    	angle=Math.round((float)(Math.asin(y/z)/Math.PI*180));
    	return angle; 
    } 

    
    public static BufferedImage rotate(Image src, int angel) {  
        int srcWidth = src.getWidth(null );  
        int srcHeight = src.getHeight(null);  
        // calculate the new image size  
//        Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(  
//                src_width, src_height)), angel); 
        Rectangle rectDes = new Rectangle(new Dimension(srcWidth, srcHeight));
        BufferedImage res = null;  
        res = new BufferedImage(rectDes.width, rectDes.height,  
                BufferedImage.TYPE_INT_RGB);  
        Graphics2D g2 = res.createGraphics();  
        Graphics2D g3 = res.createGraphics();
        // transform 
        g2.translate((rectDes.width - srcWidth)  ,  
                (rectDes.height - srcHeight)  );  
        g2.rotate(Math.toRadians(angel), 0  , 0 );  
        g3.setPaint(Color.WHITE);
        g3.fill(rectDes);
        g2.drawImage(src, null, null);
        System.err.println(res);
        try {
			ImageIO.write(res,"png",new File("D:/tupian/22.jpg"));
		} catch (IOException e) {
			e.printStackTrace();
		}
        return res;  
    }  

    public static Rectangle calcRotatedSize(Rectangle src, int angel) {  
        // if angel is greater than 90 degree, we need to do some conversion  
    	int ang=90;
        if (angel >= ang) {  
//            if(angel / 90 % 2 == 1){  
//                int temp = src.height;  
//                src.height = src.width;  
//                src.width = temp;  
//            }  
            angel = angel % ang;  
        }  

        double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;  
        double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;  
        double angelAlpha = (Math.PI - Math.toRadians(angel)) / 2;  
        double angelDaltaWidth = Math.atan((double) src.height / src.width);  
        double angelDaltaHeight = Math.atan((double) src.width / src.height);  

        int lenDaltaWidth = (int) (len * Math.cos(Math.PI - angelAlpha  
                - angelDaltaWidth));  
        int lenDaltaHeight = (int) (len * Math.cos(Math.PI - angelAlpha  
                - angelDaltaHeight));  
        int desWidth = src.width + lenDaltaWidth * 2;  
        int desHeight = src.height + lenDaltaHeight * 2;  
        return new java.awt.Rectangle(new Dimension(desWidth, desHeight));  
    }  
 

}

  

推荐阅读