zoukankan      html  css  js  c++  java
  • java中 awt Graphics2D

    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 more

    Java 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










  • 相关阅读:
    解题:POI 2006 Periods of Words
    解题:NOI 2014 动物园
    1483. 最高平均分
    1438. 较大分组的位置(回顾)
    1258. 漂亮子数组
    1903. 部门统计(回顾)
    1509. 柠檬水找零
    1451. 到最近的人的最大距离
    1425. 比较含退格的字符串
    1394. 山羊拉丁文
  • 原文地址:https://www.cnblogs.com/softidea/p/9210691.html
Copyright © 2011-2022 走看看