如何使用Graphics2D在一张图片上画线(包括箭头)
生活随笔
收集整理的這篇文章主要介紹了
如何使用Graphics2D在一张图片上画线(包括箭头)
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
有這樣一個(gè)需求,在一張圖片上畫幾條線并保存,如圖所示:
已知各個(gè)點(diǎn)的x,y坐標(biāo),坐標(biāo)范圍是[0.000,1],即將橫縱方向分成1000份。
我們可以使用java.awt.Graphics2D的庫(kù)來(lái)實(shí)現(xiàn)。
Graphics2D在Graphics類提供繪制各種基本的幾何圖形的基礎(chǔ)上進(jìn)行擴(kuò)展,擁有更強(qiáng)大的二維圖形處理能力,提供坐標(biāo)轉(zhuǎn)換、顏色管理以及文字布局等更精確的控制。Graphics2D類重要的屬性包含以下幾個(gè)
- stroke屬性
控制線條的寬度、筆形樣式、線段連接方式或短劃線圖案 - paint屬性
控制填充效果 - transform屬性
實(shí)現(xiàn)常用的圖形平移、縮放和斜切等變換操作 - clip屬性
實(shí)現(xiàn)剪裁效果 - composit屬性
設(shè)置圖形重疊區(qū)域的效果 - color
控制顏色,使用RGB構(gòu)造 - Graphics2D類的繪圖draw()
擴(kuò)充了Graphics的許多方法,可以畫線段、矩形、橢圓、圓弧、二次曲線甚至三次曲線等
相關(guān)代碼如下:
import javax.imageio.ImageIO; import java.awt.*; import java.awt.geom.Line2D; import java.awt.geom.RoundRectangle2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List;/*** @author 94977* @create 2018/12/22*/ public class JfreeChart {/*** 線寬,這里默認(rèn)設(shè)置所有線寬都一樣,也可根據(jù)需求分別設(shè)置*/private static final float STROKE_WIDTH = 3.0f;/*** 箭頭的高度,單位像素*/private static final Integer ARROW_HEIGHT = 40;/*** 箭頭底邊的一半,單位像素*/private static final Integer ARROW_LENGTH = 20;public static void main(String[] args) throws IOException {File imgFile = new File("D:\\3.jpg");File imgFile2 = new File("D:\\11.jpg");BufferedImage srcimg = ImageIO.read(imgFile);//Graphics2D對(duì)象相當(dāng)于畫筆Graphics2D g2d = srcimg.createGraphics();// 獲取圖片寬度int width = srcimg.getWidth();// 獲取圖片高度int height = srcimg.getHeight();// 設(shè)置線的型式Stroke stroke = new BasicStroke(STROKE_WIDTH, // 線寬BasicStroke.CAP_SQUARE, // 端點(diǎn)樣式BasicStroke.JOIN_BEVEL, // 接頭樣式15.0f, // 拼接限制null, // 虛線5.0f); //虛線的設(shè)置g2d.setStroke(stroke);//畫方向線g2d.setColor(new Color(255, 200, 0));List<CoordinateDto> list2 = new ArrayList<>();list2.add(new CoordinateDto(0.450,0.650));list2.add(new CoordinateDto(0.550,0.300));getDirectionLine(list2,width,height,g2d);//畫檢測(cè)線,需至少兩個(gè)點(diǎn)g2d.setColor(Color.GREEN);List<CoordinateDto> list = new ArrayList<>();list.add(new CoordinateDto(0.400,0.250));list.add(new CoordinateDto(0.450,0.500));list.add(new CoordinateDto(0.600,0.600));list.add(new CoordinateDto(0.750,0.400));for(int i = 0 ; i < list.size()-1; i++){g2d.draw(getLine(list.get(i).getX(),list.get(i).getY(),list.get(i+1).getX(),list.get(i+1).getY(),width,height));}//g2d.fill3DRect(500,400,100,5,true);//畫一個(gè)矩形//RoundRectangle2D rRect = new RoundRectangle2D.Double(13.0,30.0,100.0,70.0,10.0,10.0);//g2d.draw(rRect);//釋放此圖形的上下文并釋放它所使用的所有系統(tǒng)資源g2d.dispose();ImageIO.write(srcimg, "JPG", imgFile2);}private static void getDirectionLine(List<CoordinateDto> list, int width, int height, Graphics2D g2){CoordinateDto startPoint = list.get(0);CoordinateDto endPoint = list.get(1);int sx = (int)(startPoint.getX()*width);int sy = (int)(startPoint.getY()*height);int ex = (int)(endPoint.getX()*width);int ey = (int)(endPoint.getY()*height);drawAL(sx, sy, ex, ey, g2);}/*** 畫箭頭*/private static void drawAL(int sx, int sy, int ex, int ey, Graphics2D g2) {double H = ARROW_HEIGHT; // 箭頭高度double L = ARROW_LENGTH; // 底邊的一半int x3 = 0;int y3 = 0;int x4 = 0;int y4 = 0;double awrad = Math.atan(L / H); // 箭頭角度double arraow_len = Math.sqrt(L * L + H * H); // 箭頭的長(zhǎng)度double[] arrXY_1 = rotateVec(ex - sx, ey - sy, awrad, true, arraow_len);double[] arrXY_2 = rotateVec(ex - sx, ey - sy, -awrad, true, arraow_len);double x_3 = ex - arrXY_1[0]; // (x3,y3)是第一端點(diǎn)double y_3 = ey - arrXY_1[1];double x_4 = ex - arrXY_2[0]; // (x4,y4)是第二端點(diǎn)double y_4 = ey - arrXY_2[1];Double X3 = new Double(x_3);x3 = X3.intValue();Double Y3 = new Double(y_3);y3 = Y3.intValue();Double X4 = new Double(x_4);x4 = X4.intValue();Double Y4 = new Double(y_4);y4 = Y4.intValue();//起始線g2.drawLine(sx, sy, ex, ey);//箭頭g2.drawLine(ex, ey, x3, y3);g2.drawLine(ex, ey, x4, y4);//三角形箭頭//GeneralPath triangle = new GeneralPath();//triangle.moveTo(ex, ey);//triangle.lineTo(x3, y3);//triangle.lineTo();//triangle.closePath();//實(shí)心箭頭//g2.fill(triangle);//非實(shí)心箭頭//g2.draw(triangle);}// 計(jì)算private static double[] rotateVec(int px, int py, double ang,boolean isChLen, double newLen) {double mathstr[] = new double[2];// 矢量旋轉(zhuǎn)函數(shù),參數(shù)含義分別是x分量、y分量、旋轉(zhuǎn)角、是否改變長(zhǎng)度、新長(zhǎng)度double vx = px * Math.cos(ang) - py * Math.sin(ang);double vy = px * Math.sin(ang) + py * Math.cos(ang);if (isChLen) {double d = Math.sqrt(vx * vx + vy * vy);vx = vx / d * newLen;vy = vy / d * newLen;mathstr[0] = vx;mathstr[1] = vy;}return mathstr;}private static Line2D getLine(double x1 ,double y1,double x2 ,double y2, int width, int height){return new Line2D.Double(x1*width,y1*height,x2*width,y2*height);}} public class CoordinateDto {private double x;private double y;//省略getter setter }主要使用的是Graphics2D.drawLine()方法,注意這個(gè)方法參數(shù)里坐標(biāo)是以像素為單位,所以代碼中對(duì)此進(jìn)行了些轉(zhuǎn)換。
相關(guān)鏈接:
stroke屬性詳解
對(duì)圖像像素點(diǎn)的處理
總結(jié)
以上是生活随笔為你收集整理的如何使用Graphics2D在一张图片上画线(包括箭头)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 学习springboot基础必备
- 下一篇: 全局性事务控制如何在springboot