我正在用Java Swing和AWT(Java 8)设计一个GUI,我正在努力使用我使用的图标。
我加载一个大的PNG图像并将其缩放到18x18px,然后在按钮或标签中使用它。当操作系统不放大时,它在所有分辨率下都能很好地工作。
然而,随着大屏幕分辨率(hidpi)的出现,使用操作系统设置放大用户交互界面控件是一种常见的做法,包括Java应用程序中的按钮等。例如,在Windows上,我使用具有4K分辨率的150%或200%的用户元素缩放来确保用户交互界面仍然可用。我想许多用户也会这样做。
然而,在这种情况下,图标只是在缩小到18x18px后才增加大小。也就是说,我首先缩小它们的比例,然后操作系统尝试使用图像中仍然保留的少量信息再次放大它们。
当使用操作系统的缩放功能以避免图像模糊时,有没有办法在Java中设计基于更高分辨率的图像图标?
这是一个工作示例:
import java.awt.Container;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
@SuppressWarnings("serial")
class Example extends JFrame {
public static void main(String[] args) {
new Example();
}
public Example() {
Container c = getContentPane();
JPanel panel = new JPanel();
ImageIcon icon = new ImageIcon(new ImageIcon(getClass().getResource("tabler-icon-beach.png")).getImage().getScaledInstance(18, 18, Image.SCALE_SMOOTH));
JButton button = new JButton("Test button", icon);
panel.add(button);
c.add(panel);
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
}
您可以在此处找到图标。所有图标都可以作为PNG或SVG文件使用。
为了说明这个问题,首先让我以正常的100%屏幕分辨率向您展示两个屏幕截图:
在100%缩放的Linux上:
在100%缩放的窗口上:
现在,当我将Windows 7设置为布局元素放大200%时,显然只是18x18px版本的扩展,变得模糊了:
当操作系统使用大于100%的缩放比例时,有没有办法提供更高分辨率的图像图标?此外,你可以看到,即使在100%的图像质量是不完美的;还有什么方法可以改进吗?
Java 8不支持高DPI,用户界面由Windows扩展。您应该使用支持每监视器高DPI设置的Java 11或更高版本。
如果您的目标是让图标看起来清晰,请使用BaseMultiResolutionImage
(MultiResolutionImage
的基本实现)为不同分辨率准备一组图标,以提供更高分辨率的替代方案。(这些在Java8中不可用。)
您说您将原始图像(240×240)缩小到18×18px。根据系统设置,如果用户界面需要更高的分辨率,那么它现在只有你的小图标(18×18),它将被放大,从而导致质量较差。您应该使用多分辨率图像(MultiResolutionImage)或将原始图像绘制成所需大小,让图形为您缩小比例。
这是我想到的在不缩小原始图像的情况下制作图标18×18的最简单方法:
private static final String IMAGE_URL =
"https://tabler-icons.io/static/tabler-icons/icons-png/beach.png";
private static ImageIcon getIcon() {
return new ImageIcon(Toolkit.getDefaultToolkit()
.getImage(new URL(IMAGE_URL))) {
@Override
public int getIconWidth() {
return 18;
}
@Override
public int getIconHeight() {
return 18;
}
@Override
public synchronized void paintIcon(Component c, Graphics g,
int x, int y) {
g.drawImage(getImage(), x, y, 18, 18, null);
}
};
}
我遗漏了可以从URL
构造函数抛出的MalformedURLException
的异常处理代码。
在这种情况下,绘制的图像每次绘制时都会缩小,这是无效的。然而,质量更好。嗯,对于标准分辨率的屏幕,它几乎与加载时缩小图像的比例相同。但在高DPI的情况下,它看起来更好。这是因为对于200%的用户界面比例,图像将被渲染为36×36像素,这些像素将从240×240的源创建,而不是放大缩小后的版本,因为缩小后的版本失去了质量。
为了获得更好的结果,我建议使用MultiResolutionImage。
下面的应用程序从base64编码的字符串加载图像(为了简单起见,没有外部依赖关系)。提供了三种变体:24×24(100%,96dpi)、36×36(150%,144dpi)、48×48(200%,192dpi)。
如果当前比例因子设置为任何提供的分辨率,则图像将按原样渲染。如果使用125%或175%,则会缩小较大的图像;如果比例大于200%,则将放大200%的图像。如果需要,可以添加更多分辨率。
该应用程序没有在Java 8中编译,因为那里没有MultiResolutionImage。要用JDK 11编译它,必须用常规字符串连接替换文本块。
import java.awt.Image;
import java.awt.image.BaseMultiResolutionImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Base64;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class BeachIconButton {
public static void main(String[] args) {
SwingUtilities.invokeLater(BeachIconButton::new);
}
private BeachIconButton() {
JPanel panel = new JPanel();
ImageIcon icon = getIcon();
JButton button = new JButton("Test button", icon);
panel.add(button);
JFrame frame = new JFrame("Beach Icon Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static ImageIcon getIcon() {
return new ImageIcon(
new BaseMultiResolutionImage(
Arrays.stream(new String[] { BEACH_100, BEACH_150, BEACH_200})
.map(BeachIconButton::loadImage)
.toArray(Image[]::new)));
}
private static Image loadImage(String base64) {
try {
return ImageIO.read(new ByteArrayInputStream(
Base64.getMimeDecoder().decode(base64)));
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private static final String BEACH_100 = """
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAA7DAAAO
wwHHb6hkAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAXxJ
REFUSInl1E9LVVEUBfAfVJBIIoWGIDiRGtagN7Yg+gTZXPwICU4FyUGDahBRCTrK
qUVNIxrkJHjWJMKZikIjSyHoYd0GZ186vOef7n2zWnB4e591WXudt/c5/G8Ywiw+
4gd28QGLuNCt+C18RXHI+onJuuLjIVBgGWOYyPb2syI3q4qfzZw/ir1raMXeNBay
k+zgfNUC25nTBWxGPhfffI78XfzOVD1FP+5lrgusoweXIv+C6xE3qxYocRFrWZHv
eBPxA5yJeK9ugRJPdU7QGPoi3+1GfFBqZIFn+BVxC88jft9NgdL9q8gH8MSfUa3V
5BKXQ6gl9aOdey1N2GBV4VO4ik/h8CWG67rMcQ53Hf5ErOBGXfEGtjKxVSxhHi/w
LeMe4mQV8ROZ67fSZWrHadyW7kKBqaonuC89Bcc5uyKNZ+M4wTvS9d/AY/RmXK80
iht/wa+HVgfKB61cTYzGaups8FH89kEFhjBSUzDnR0LrSFT5Sw7i/yH8BmQ0mnmX
f2wqAAAAAElFTkSuQmCC""";
private static final String BEACH_150 = """
iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAACXBIWXMAABYlAAAW
JQFJUiTwAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAoVJ
REFUWIXt1kuoTVEYB/DfdZWiq7gykZBHHokyw0QGREpKLgMDGSojQ6+JARFi4JFn
ySPyyoCJR8zcIUVJiPLopiMhLoO1d3ftc+7Z95xrnYHyr1V7feu/1/ff3/etby/+
4x9DW8K9ZmE9FmTP7fiBp3iE03iS0F9dTMQN/G5gvMLMVopZhi8NisnHD6xohZiV
2ea5o584h+WYgAclor5jaUoxE9ATOXiOednaUMUU9mKPkK5YVCXbJwkuKkZmYbS2
t8rxpsz+QW2krqYSdF5tCnZjCX5F9h0Zf25k66nizEghaBSOV22cRyt/vhnxd0b2
E7gQzXelEJRjnv6L96dQ9IR+9CxaWymcsnx+L6UgQnPtUizyfDwRaiiff8JwjIts
71MLytGBy0I9xaLitG7LuCMi2+d4kyEJBVWwWkhPfz568UaI6Mho/XtCDTXYqO/L
v+GF2jQ+wNZofrdVYjrwNnK0XYjOYSEt9bp20lMWY0/k5LVQJzlGCn2qur56Mb0V
YiYLKcodddXhTcX1iJesU1cj/nc9NPA9axE2Cw02GUYITe6UYgoOCv+29pTOyjAH
VxRT1N/4iP0Y2yohHTij9v810Khgiwavy43eqSfhGmZHtt/oxm2h4fUI0Zim75IW
4wI24GuDPutiCF4q1sklAx/XJXisGK2zfysGhum7N3/F2ibebce+SNCdFIJgMQ4J
F63BYBUOYEqzL87HLaEeKrivPCLrMk5lEPyezNf8MkHv9H9STioegDbF/vM3/Hdl
grpLnBxFJ8bgWAmvWX53maBOId/jMRpHGnB8JOM2yx+f+eosE1SNNiH89TY/oTY1
zfAHjS7hMv45G3exJiH/P/5d/AHE21JDZYKOHAAAAABJRU5ErkJggg==""";
private static final String BEACH_200 = """
iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAB2HAAAd
hwGP5fFlAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAA5FJ
REFUaIHt2ctrXFUcB/BPYoWGVGOwBZtYQQoqhUp9IFEoulC04spGExQEpYoiVBBc
qVAVwYX/gEWqooKboItqN4oV0frWPgR3XRSl9mHT2GjaJh0X5w6ZOXPuzO08roL5
wlnM+T3O93cev3vOb1jCEv7f6CtpnBswjg1Yh2HM4wx+wh58jC9K4lMIfXgIB1Ap
2H7FC7jwX+Bbh2uwW3HiqUDWlE26io040YJgkXYKd5TM3Z34K0HmNKYwgavxgLD/
WwUxi1vKIr8GfyRIfIAravTuxtmE3g+Jvkrm86pek+/XuOfP4elIbz1mIr15bBUm
IG8lPtHjjLkpMeg+jNboDOKXSOcsJjP5bU0CqODBsgOoHsRnsRyvJ+RP1vh4PpId
in7v7WUA/diRE0QFhxN92yMfeyL5MxoP+nW9DAJuxY85QdS2AxiosVsrnJmqfAGX
4/3I7uVeBwAX4DEcaRLAFFbV2LwSyXdn/ZNR/86es6/BCmyTTpnVWX4Tl2pMv49k
PtZF/QfLIl+L9fhN/mrEK3XE4vYajGQzZRKPcTuOyw+k2rbV2FwSyY7GTvt7yTjC
UQwV0FspEKf+nMBcVxmdJz7VeEVYkF6F43gKD0f9H5bOOsN9Gkluws04lpBV21z0
+7myiRO+wgcjInE6HE/opNpYOZTrEV8RzghX6hjLhWvHKWny35RBNsZogtCrLWxG
8JrG8zHRO5r5eCci8bvFDNMKY/hMeNRsF77wpWJM/f2mgke7PciyLvtbKby4NuJe
9Y+QGdyEv7FLSJX/CfThfqGmM691Jqlkep8L6bWs2lQSd+F7xUjnte+EYkCpGMQb
HRKP247M73mhneVbhY9wY0J2TpjRnUKV4bBQIxrGalyPe4RSY+oe9q1who61wasQ
+vC1xtlbwFu4sqCftXhb+i70lR6ei+HEgPtxbZv+NuDnhM/hjpnmoE+YoepAu7Sx
byOsELZkWyvQzlINCTWaGbwnpMROsUx4/16Md3GyE2cDQqXsS0wLRPfhJfWFqjyM
Zrr78WcX7KczLlvVVzJyMSU/1U1brKSlMJnp9Mp+qkgAs00cVL+imxN244p9iTux
ny0SQLMVqLY5PCHs2SGhRHi6gF2n9oVWYABbhOLUZbgoGyx+3rUi+Hhm26n96ozL
FgXPQB4262yLdGrfFUxo/vfRCc1fTp3adwUjeFEod5/M2l7h38WREuyXsIQl1OAf
9zFZ1uiy3BkAAAAASUVORK5CYII=""";
}
我有一些. jpg,我正在面板中显示。不幸的是,它们都是大约1500x1125像素,这对我来说太大了。有没有一种编程方法来改变这些. jpg的分辨率?
我有一个java的列表。awt。图像,每个分辨率为300 DPI。我想打印它们,当我开始打印这些图像时(使用javax.PrintService API),只打印一些图像的一部分,因为Java的打印/3D类默认使用72DPI(相对于我的图像的300 DPI)。但是,当我使用72 DPI的图像(与Java默认值具有相同的分辨率)时,所有图像都可以很好地打印(打印整个图像时,而不仅仅是其中的一部分)。
然后,我根据页面大小与图像大小计算缩放的维度,返回:java.awt.dimension[width=562,height=792]我使用下面的代码来计算缩放的维度: 为了实际执行图像缩放,我使用image Scalr API: 我的问题是我做错了什么?当缩放到较小的尺寸时,大的图像不应该被模糊。这与PDF页面的分辨率/大小有关吗?
我希望高质量的图像显示在中,并上传到服务器。我搜索了互联网、StackOverflow和GitHub,但我找不到答案,也许有人知道如何修复它? : 这里怎么了?
Android SDK提供了以下图标。 有没有办法给那些设置颜色...如果可能的话,怎么做? 使现代化 在对项目进行了完整的刷新之后,发现Xml中的属性起到了作用。 简而言之 ...这是为我工作的解决方案-将属性添加到ImageView xml: 来自@goldenb的答案是对解决这个问题的不同方法的全面介绍,所以我将其标记为答案。
问题内容: 我需要使用Java程序减小图像的大小(而不是宽度和高度)。他们为此提供了任何好的API吗? 我需要将大小从1MB减少到大约50kb-100 kb。当然,分辨率会降低,但这并不重要。 问题答案: 这是工作代码 这段代码对我来说很棒。如果需要调整图像大小,则可以在此处更改x和y比例J;