Graphics2D ,Graphics 類,提供了對幾何形狀、坐標轉換、顏色管理和文本布局更為復雜的控制。它是用於在 Java(tm) 平台上呈現二維形狀、文本和圖像的基礎類。驗證碼生成可以用到此類。
public abstract class Graphics2D extends Graphics 此 Graphics2D 類擴展了 Graphics 類,提供了對幾何形狀、坐標轉換、顏色管理和文本布局更為復雜的控制。
創建 Graphics2D 對象時,GraphicsConfiguration 將為 Graphics2D 的目標(Component 或 Image)指定默認轉換,此默認轉換將用戶空間坐標系統映射到屏幕和打印機設備坐標,
這樣,原點映射到設備目標區域的左上角,並將 X 坐標軸向右方延伸,將 Y 坐標軸向下方延伸。
對於接近 72 dpi 的設備(例如屏幕設備),默認轉換的縮放比例設置為恆等。
對於高分辨率設備(例如打印機),默認轉換的縮放比例設置為每平方英寸大約 72 個用戶空間坐標。對於圖像緩沖區,默認轉換為 Identity 轉換。
java2D繪圖流程
如果要繪制一個形狀,可以按照如下步驟操作:
1)獲得一個Graphics2D類的對象,該類是Graphics類的子類。
public void paintComponent()
{
Graphics2D g2 = (Graphics2D) g;
}
2)使用setRenderingHints方法來設置繪圖提示,它提供了速度與繪圖質量之間的一種平衡。
RenderingHits hints = ...;
g2.setRenderingHints(hints);
3)使用setStroke方法來設置筆划,筆划用於繪制形狀的邊框。可以選擇邊框的粗細和線段的虛實。
Stroke stroke = ...;
g2.setStroke(stroke);
4)使用setPaint方法來設置着色方法。着色方法用於填充諸如筆划路徑或者形狀內部等區域的顏色。可以創建單色的着色法,也可
以用變化的色調進行着色,或者使用平鋪的填充模式。
Paint paint = ...;
g2.setPaint(paint);
5)使用clip方法來設置剪切區域。
Shape clip = ...;
g2.clip(clip);
6)使用transform方法,設置一個從用戶空間到設備空間的變換方式。如果使用變換方式比使用像素坐標更容易地定義在定制坐標系
統中的形狀,那么就可以使用變換方式。
AffineTransform transform = ...;
g2.transform(transform);
7)使用setComposite方法設置一個組合規則,用來描述如何將新像素與現有的像素組合起來。
Composite composite = ...;
g2.setComposite(composite);
8)建立一個形狀,java2D API提供了用來組合各種形狀的許多形狀對象和方法。
Shape shape = ...;
9)繪制或者填充該形狀。如果要繪制該形狀,那么它的邊框就會用筆划畫出來;如果要填充該形狀,那么它的內部就會被着色。
g2.draw(shape);
或
g2.fill(shape);
在繪圖流程中,需要以下這些操作步驟來繪制一個形狀:
1)用筆划畫出形狀的線條;
2)對形狀進行變換操作;
3)對形狀進行剪切。如果形狀與剪切區域之間沒有任何相交的地方,那么就停止本次操作;
4)對剪切后的形狀的剩余部分進行填充;
5)把填充后的形狀的像素與已有的像素進行組合
The following code always seems to fail:
URL url = new URL("http://userserve-ak.last.fm/serve/126/8636005.jpg"); Image img = ImageIO.read(url); System.out.println(img);
I've checked the url, and it is a valid jpg image. The error I get is:
Exception in thread "main" javax.imageio.IIOException: Can't get input stream from URL!
at javax.imageio.ImageIO.read(ImageIO.java:1385)
at maestro.Main2.main(Main2.java:25)Caused by: java.net.ConnectException: Connection timed out
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:310)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:176)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:163)
at java.net.Socket.connect(Socket.java:546)
at java.net.Socket.connect(Socket.java:495)
at sun.net.NetworkClient.doConnect(NetworkClient.java:174)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:409)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:530)
at sun.net.www.http.HttpClient.(HttpClient.java:240)
at sun.net.www.http.HttpClient.New(HttpClient.java:321)
at sun.net.www.http.HttpClient.New(HttpClient.java:338)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:814)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:755)
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:680)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1005)
at java.net.URL.openStream(URL.java:1029)
at javax.imageio.ImageIO.read(ImageIO.java:1383)
... 1 moreJava Result: 1
What does this mean? Funny thing is, if I change my internet-connection to that of the neighbour's wireless, it suddenly works.
This worked for me. :)
URL url = new URL("http://userserve-ak.last.fm/serve/126/8636005.jpg"); Image image = ImageIO.read(url.openStream()); System.out.println(image);
I know I am late. Since, even I faced the same issue, thought of putting as it would help some one. :)
http://www.it1352.com/544832.html圖片處理
首先畫布肯定是需要的,可以新建一個空白畫布,也可以以圖片做畫布。
BufferedImage bi = new BufferedImage(width,height,type);
2d = bi.createGraphics();
如果需要生成RGB格式,需要做如下配置
bi = 2d.getDeviceConfiguration().createCompatibleImage(width,height,Transparency.TRANSLUCENT);
注:參數width 和 height 要和是前面畫布的對應。
Transparency透明度設置
畫圖 g.drawImage(img,x,y,width,hight);
注:參數x,y為圖片左上角坐標
旋轉處理 AffineTransform atf.rotate(theta,x,y)
注:theta這兒的角度需要轉換成弧度數
x,y為旋轉中心坐標,圖片旋轉參考點為圖片的中心點
同時有偏移、縮放、旋轉操作時,畫圖順序為:縮放-->偏移-->旋轉
【設置抗鋸齒屬性】 //消除文字鋸齒 g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON); //消除畫圖鋸齒 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
解決Graphics2D drawImage圖片失真的問題
常規的寫法
graphics.drawImage(originalBufferedImage, rectangle.x, rectangle.y, rectangle.width, rectangle.height, null);
優化的寫法
graphics.drawImage( originalBufferedImage.getScaledInstance(rectangle.width, rectangle.height, Image.SCALE_SMOOTH), rectangle.x, rectangle.y, null);
字體處理
Graphics2D 處理字體的做法和處理圖片的大體一致
1、最需要注意的一點就是 在畫字體的時候 x,y坐標為字體左左左左下角
2、旋轉中心可以通過獲取字體的行高和字字符串寬度對應的api計算獲得
3、最好用同一包中的字體ttf。如果混用,圖片在處理縮放時會存在差異,即使用的字體類型、大小、樣式都一致,同樣可能會存在差異
https://blog.csdn.net/qq_31482599/article/details/78929670
Linux下采用Graphics2D中文亂碼
1、下載simsun.ttc
2、把該文件復制到$JAVA_HOME/jre/lib/fonts目錄下,改名為simsun.ttf
3、重啟Java進程
import java.awt.*; import java.awt.font.*; import java.awt.geom.*; import javax.swing.*; /** * @version 1.33 2007-04-14 * @author Cay Horstmann */ public class FontTest { public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { FontFrame frame = new FontFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }); } } /** * A frame with a text message component */ class FontFrame extends JFrame { public FontFrame() { setTitle("FontTest"); setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); // add component to frame FontComponent component = new FontComponent(); add(component); } public static final int DEFAULT_WIDTH = 300; public static final int DEFAULT_HEIGHT = 200; } /** * A component that shows a centered message in a box. */ class FontComponent extends JComponent { public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; String message = "Hello, World!"; Font f = new Font("Serif", Font.BOLD, 36); g2.setFont(f); // measure the size of the message FontRenderContext context = g2.getFontRenderContext(); Rectangle2D bounds = f.getStringBounds(message, context); // set (x,y) = top left corner of text double x = (getWidth() - bounds.getWidth()) / 2; double y = (getHeight() - bounds.getHeight()) / 2; // add ascent to y to reach the baseline double ascent = -bounds.getY(); double baseY = y + ascent; // draw the message g2.drawString(message, (int) x, (int) baseY); g2.setPaint(Color.LIGHT_GRAY); // draw the baseline g2.draw(new Line2D.Double(x, baseY, x + bounds.getWidth(), baseY)); // draw the enclosing rectangle Rectangle2D rect = new Rectangle2D.Double(x, y, bounds.getWidth(), bounds.getHeight()); g2.draw(rect); } }
ISBN: 978-0134177304 | 978-0134177298
Both volumes are available as e-books: Volume I—Fundamentals | Volume II—Advanced Features
Core Java by Cay S. Horstmann and Gary Cornell was originally published in the Java series of Sun Microsystems Press and is now published by Prentice-Hall. The book is aimed at experienced programmers who want to learn how to write useful Java applications and applets. No hype, no toy code, no language lawyering, just solid facts and in-depth research to help you write real programs.
“What makes Core Java the definitive work on the language is more than its vast scope—it is the quality of the presentation.”—Andrew Binstock
“Cornell and Horstmann make the details of this powerful and expressive language understandable, and they also furnish a conceptual model for its object-oriented foundations.”—Grady Booch.
“Devoid of shaky, academic examples and packed with robust demonstrations that illustrate hundreds of powerful concepts...The authors back up the many examples with sharp, fact-rich commentary on how to get things done with Java.”—David Wall
http://horstmann.com/corejava.html
import lombok.extern.slf4j.Slf4j; import javax.imageio.ImageIO; import java.awt.*; import java.awt.font.FontRenderContext; import java.awt.font.TextLayout; import java.awt.geom.AffineTransform; import java.awt.geom.Ellipse2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.net.URL; /** * spring-boot-cookbook * * @author tangcheng * @date 6/25/2018 12:03 AM */ @Slf4j public class VotePosterBuilder { private BufferedImage templateImage = null; private Graphics2D graphics2D; private int templateWidth; private int templateHeight; public VotePosterBuilder(String templateUrl) { try { URL url = new URL(templateUrl); templateImage = ImageIO.read(url.openStream()); graphics2D = templateImage.createGraphics(); RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); rh.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); rh.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); rh.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); graphics2D.setRenderingHints(rh); templateWidth = templateImage.getWidth(); templateHeight = templateImage.getHeight(); } catch (IOException e) { log.error("fail to read templateUrl:{}", templateUrl, e); } } public VotePosterBuilder addQrcode(String qrCodeImageUrl) throws IOException { URL url = new URL(qrCodeImageUrl); BufferedImage qrcodeImage = ImageIO.read(url.openStream()); int x = templateWidth * 3 / 8; int y = templateHeight * 3 / 4; int width = templateWidth / 4; int height = templateWidth / 4; graphics2D.drawImage(qrcodeImage, x, y, width, height, null); return this; } public VotePosterBuilder addHeadImage(String headImageUrl) throws IOException { URL url = new URL(headImageUrl); BufferedImage headImage = ImageIO.read(url.openStream()); int x = 470; int y = 520; int width = 190; int height = 190; Shape olcClip = graphics2D.getClip(); Stroke oldStroke = graphics2D.getStroke(); BasicStroke s = new BasicStroke(20f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); graphics2D.setStroke(s); Ellipse2D.Double shape = new Ellipse2D.Double(x, y, width, height); // graphics2D.fill(new Rectangle(templateWidth, templateWidth)); graphics2D.setStroke(new BasicStroke(1f)); // graphics2D.setColor(Color.WHITE); graphics2D.setColor(Color.green); graphics2D.draw(shape); graphics2D.clip(shape); headImage.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH); graphics2D.drawImage(headImage, x, y, null); // graphics2D.setColor(Color.WHITE); // shape = new Ellipse2D.Double(x, y, width - 1, height - 1); // graphics2D.drawOval(x, y, width, height); // graphics2D.draw(shape); graphics2D.setClip(olcClip); graphics2D.setStroke(oldStroke); // graphics2D.drawImage(headImage, x - width - 10, y, width, height, null); return this; } public VotePosterBuilder addNickname(String nickname) { Font oldFont = graphics2D.getFont(); Color oldColor = graphics2D.getColor(); Stroke oldStroke = graphics2D.getStroke(); Font font = new Font("Serif", Font.BOLD, 50); Rectangle2D bounds = font.getStringBounds(nickname, graphics2D.getFontRenderContext()); double x = (templateWidth - bounds.getWidth()) / 2; double y = (templateHeight - bounds.getHeight()) / 2; double ascent = -bounds.getY(); double baseY = y + ascent - 50; log.info("x:{},baseY:{}", x, baseY); graphics2D.setFont(font); graphics2D.setColor(Color.blue);//設置當前繪圖顏色 graphics2D.drawString(nickname, (int) x, (int) baseY); FontRenderContext frc = graphics2D.getFontRenderContext(); TextLayout tl = new TextLayout("不錯", new Font("宋體", Font.PLAIN, 50), frc); Shape sha = tl.getOutline(AffineTransform.getTranslateInstance(5, 100)); graphics2D.setStroke(new BasicStroke(10.0f)); graphics2D.setColor(Color.WHITE); graphics2D.draw(sha); graphics2D.setColor(Color.BLACK); graphics2D.fill(sha); graphics2D.setFont(oldFont); graphics2D.setColor(oldColor); graphics2D.setStroke(oldStroke); return this; } public void build() { graphics2D.dispose(); templateImage.flush(); try { File output = new File("poster.jpg"); ImageIO.write(templateImage, "jpg", output); log.info("output:{}", output.getAbsolutePath()); } catch (Exception e) { log.error(e.getMessage(), e); } System.gc(); } }
https://blog.csdn.net/sjdl9396/article/details/7440424
Java中Swing繪制只有一個圓角的邊框
https://blog.csdn.net/tokimemo/article/details/33722157
import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.Transparency; import java.awt.geom.Ellipse2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; public class TestTT { public static void main(String[] args) throws IOException { BufferedImage bi1 = ImageIO.read(new File("d:/1.jpg")); // 根據需要是否使用 BufferedImage.TYPE_INT_ARGB BufferedImage image = new BufferedImage(bi1.getWidth(), bi1.getHeight(), BufferedImage.TYPE_INT_RGB); Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, bi1.getWidth(), bi1 .getHeight()); Graphics2D g2 = image.createGraphics(); image = g2.getDeviceConfiguration().createCompatibleImage(bi1.getWidth(), bi1.getHeight(), Transparency.TRANSLUCENT); g2 = image.createGraphics(); g2.setBackground(Color.RED); g2.fill(new Rectangle(image.getWidth(), image.getHeight())); g2.setClip(shape); // 使用 setRenderingHint 設置抗鋸齒 g2.drawImage(bi1, 0, 0, null); g2.dispose(); try { ImageIO.write(image, "PNG", new File("d:/2.png")); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
見最后一個回答:
http://stackoverflow.com/questions/2642577/transparency-in-bufferedimage-objects
BufferedImage bi1 = ImageIO.read(new File("d:/1.jpg")); // 根據需要是否使用 BufferedImage.TYPE_INT_ARGB BufferedImage image = new BufferedImage(bi1.getWidth(), bi1.getHeight(), BufferedImage.TYPE_INT_ARGB); Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, bi1.getWidth(), bi1 .getHeight()); Graphics2D g2 = image.createGraphics(); image = g2.getDeviceConfiguration().createCompatibleImage(bi1.getWidth(), bi1.getHeight(), Transparency.TRANSLUCENT); g2 = image.createGraphics(); g2.setComposite(AlphaComposite.Clear); g2.fill(new Rectangle(image.getWidth(), image.getHeight())); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, 1.0f)); g2.setClip(shape); // 使用 setRenderingHint 設置抗鋸齒 g2.drawImage(bi1, 0, 0, null); g2.dispose(); try { ImageIO.write(image, "PNG", new File("d:/2.png")); } catch (IOException e) { e.printStackTrace(); }
/** * 圓角處理 * * @param srcImageFile * @param result * @param type * @param cornerRadius 720的時候就處理為圓 * @return */ public static String makeRoundedCorner(String srcImageFile, String result, String type, int cornerRadius) { try { BufferedImage image = ImageIO.read(new File(srcImageFile)); int w = image.getWidth(); int h = image.getHeight(); BufferedImage output = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = output.createGraphics(); output = g2.getDeviceConfiguration().createCompatibleImage(w, h, Transparency.TRANSLUCENT); g2.dispose(); g2 = output.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.fillRoundRect(0, 0,w, h, cornerRadius, cornerRadius); g2.setComposite(AlphaComposite.SrcIn); g2.drawImage(image, 0, 0, w, h, null); g2.dispose(); ImageIO.write(output, type, new File(result)); return result; } catch (IOException e) { e.printStackTrace(); } return null; }
https://bbs.csdn.net/topics/390934550
https://stackoverflow.com/questions/2466233/java-swing-converting-a-text-string-to-a-shape
一句話解決Thumbnails縮略圖工具PNG透明背景縮放后變黑問題
注意加紅色的部分:
Builder<BufferedImage> builder = Thumbnails.of(sourceImage).imageType(BufferedImage.TYPE_INT_ARGB).forceSize(width, height);
builder.outputFormat("png").toFile(destFile);
有人可能問thumbnailator是什么?一個縮放開源項目而已。
給個gradle地址:
api 'net.coobird:thumbnailator:0.4.8'
https://blog.csdn.net/applebomb/article/details/88734572