【问题标题】:Java Graphics 2D render quality issueJava Graphics 2D 渲染质量问题
【发布时间】:2019-01-03 02:51:26
【问题描述】:

使用 Java Graphics 2D 逐分钟渲染图像以创建延时视频,导致运行时图像模糊。全高清 (1920 X 1080) 上的图像分辨率模糊出现在图像而不是视频上。

我使用缓冲图像作为下面的配置

BufferedImage alt = config.createCompatibleImage(resX, resY);        
Graphics2D g2 = alt.createGraphics();

resXresY

final int resX = 1920;
final int resY = 1080;

尝试使用此 x,y 配置绘制圆形和文本

// Image
g2.drawImage(img, leftSideX, resYTop + paddingImg, resX - leftSideX - paddingImg, resY - resYTop - paddingImg - paddingImg, null);

// Draw Cirlce 1
g2.setColor(new Color(0,161,155));
g2.fillArc(78, 160, 200, 200, 90, -340);

g2.setColor(new Color(73, 73, 73));
g2.fillArc(98, 180, 160, 160, 90, -340);

// Percentage
g2.setColor(new Color(0,161,155));
g2.setFont(g2.getFont().deriveFont(45F)); 
g2.drawString("10%", 135, 275 );  

// Draw circle Legend
g2.setColor(new Color(0,161,155));
g2.fillArc(paddingLegend, resY - 150, paddingLegend, paddingLegend, 360, 360);

g2.setColor(new Color(249,178,52));
g2.fillArc(paddingLegend, resY - 120, paddingLegend, paddingLegend, 360, 360);

g2.setColor(new Color(190,22,35));
g2.fillArc(paddingLegend, resY - 90, paddingLegend, paddingLegend, 360, 360);

g2.setColor(new Color(178,178,178));
g2.setFont(g2.getFont().deriveFont( 15F ));
g2.drawString("Occupied / Moving Goods", paddingLegend + 30, resY - 135 );                 
g2.drawString("Goods idle > 2 days and < 5 days", paddingLegend + 30, resY - 105); 
g2.drawString("Goods idle \u2265 5 days", paddingLegend + 30, resY - 75 );          

// Capacity Level Title
g2.setFont(g2.getFont().deriveFont( 20F ));
g2.drawString("Capacity Level ", paddingLeftSubTitle + paddingLegend, resYTop + paddingTopSubTitle1 + paddingLegend); 

// Goods Movement Title
g2.setFont(g2.getFont().deriveFont( 20F ));
g2.drawString("Goods Movement ", paddingLeftSubTitle + paddingLegend, resYTop + paddingTopSubTitle2 + paddingLegend); 

这是结果

模糊出现在圆圈和文字上

从上面的图片可以看出,圆圈和文字完全模糊,但仓库图像根本不模糊。我试过下面的代码,没有任何改进。

g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);

如何提高图像渲染质量?

非常感谢

【问题讨论】:

  • 需要考虑的事项。缩放 - 一些缩放会导致抗锯齿问题。我还会查看可用的text rending hints,看看它们是否有帮助。也很难知道,但图像似乎受到 JPEG 压缩伪影的影响,但这可能只是捕获本身
  • 我在docs.oracle.com/javase/6/docs/api/java/awt/RenderingHints.html 上尝试过文本渲染提示,对我没有任何作用。如何使用缩放,但我已经将 x,y 设置为图像分辨率 1920 X 1080?
  • 问题是,你是在缩放图像吗?由于我们所拥有的只是一些脱离上下文的代码和屏幕截图,因此很难知道问题可能出在哪里
  • 无缩放。我只是在 x,y 坐标上绘制
  • 好吧,我猜不到了,考虑提供一个 runnable example 来证明您的问题

标签: java render graphics2d


【解决方案1】:

所以,当我将你的代码修补在一起并运行它时,我得到...

这对我来说似乎很好。因此,要么是您的代码中发生了我们不知道的其他事情,要么是硬件/驱动程序问题。

考虑提供Minimal, Complete, and Verifiable example - 这样可以消除猜测工作,并为我们提供更好的机会来理解问题并提供可能的解决方案

注意:我正在以 1920x1080 的分辨率渲染输出,我刚刚为帖子剪辑了输出

ps-我知道这不是“答案”,但我没有从 OP 那里得到任何帮助

CircularProgress

因为我之前没有做过一百次......

虽然您可以使用常规的 2D 图形 API 来做这种事情,但我倾向于发现“形状”API 是一种更有用的方法,尤其是对于生成复杂的可重复使用的形状

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class CircleProgressTest {

    public static void main(String[] args) {
        new CircleProgressTest();
    }

    public CircleProgressTest() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private double progress = 0d;
        private double radius = 90;
        private CircleProgress cp;

        public TestPane() {
            cp = new CircleProgress(radius, 20, 0d);
            Timer timer = new Timer(50, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (progress >= 1.0) {
                        ((Timer)(e.getSource())).stop();
                        progress = 1.0;
                    } else {
                        progress += 0.001;
                    }
                    cp = new CircleProgress(radius, 20, progress);
                    repaint();
                }
            });
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);

            double x = (getWidth() - (radius * 2d)) / 2d;
            double y = (getHeight() - (radius * 2d)) / 2d;

            g2d.transform(AffineTransform.getTranslateInstance(x, y));

            g2d.setStroke(new BasicStroke(4f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
            g2d.setColor(Color.DARK_GRAY);
            g2d.draw(cp);
            g2d.setColor(new Color(0,161,155));
            g2d.fill(cp);

            g2d.dispose();
        }

    }

    public class CircleProgress extends Path2D.Double {

        private double radius;
        private double thickness; // subtracted from radius
        private double progress;

        public CircleProgress(double radius, double thickness, double progress) {
            this.radius = radius;
            this.thickness = thickness;
            this.progress = progress;

            build();
        }

        protected void build() {
            double innerRadius = radius - thickness;
            if (progress >= 1.0) {
                Area outter = new Area(new Ellipse2D.Double(0, 0, radius * 2d, radius * 2d));
                Area inner = new Area(new Ellipse2D.Double(thickness, thickness, innerRadius * 2d, innerRadius * 2d));
                outter.subtract(inner);
                append(outter, true);
            } else if (progress <= 0.0) {
                // What does this actually mean...?
            } else {
                double extent = -(360.0 * progress);
                double startAt = 90d;

                append(new Arc2D.Double(0, 0, radius * 2d, radius * 2d, startAt, extent, Arc2D.OPEN), true);
                append(new Arc2D.Double(thickness, thickness, innerRadius * 2d, innerRadius * 2d, startAt + extent, -extent, Arc2D.OPEN), true);
                closePath();
            }
        }
    }

}

【讨论】:

  • 问题似乎出在ImageIO.write(alt, "jpg", f); 我使用ImageIO 将bufferimage 写入文件。有什么想法吗?
  • 好吧,不要用jpg开头,是松散压缩,用PNG,无损
猜你喜欢
  • 2018-09-24
  • 1970-01-01
  • 2017-11-16
  • 2020-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多