Java 如何加载原生 NSImages?
How does Java load native NSImages?
我一直在阅读 OS X Java 开发人员工具,以帮助使我的应用程序更 "native" 与操作系统兼容。我在这个特定的 section 中发现了一些有趣的东西。 (强调我的)
To load a resolution-independent tiff, icns, or pdf file from the Resources folder of your application bundle into your Java application, use the getImage()
method of java.awt.Toolkit
. The string you pass into getImage()
is of the form "NSImage://MyImage"
. Do not include the file extension of the image. Also be aware that the Sun 2D renderer is disabled when the user interface scale factor does not have a value of 1.0. Use the Quartz renderer so that your images scale smoothly.
熟悉 javax.imageio
,这完全出乎我的意料,因为我不知道有任何其他方法可以将其他文件类型加载到图像中。特别是在一个过时的平台上,并且绝对不支持 .tiff
等文件。例如,在我的计算机上进行快速测试会得到以下结果:
Supported read formats: [jpg, bmp, gif, png, wbmp, jpeg]
Supported write formats: [jpg, bmp, gif, png, wbmp, jpeg]
'JPEG' reader: com.sun.imageio.plugins.jpeg.JPEGImageReader@5e9f23b4
'JPEG' reader: com.sun.imageio.plugins.jpeg.JPEGImageWriter@378fd1ac
我尝试加载一个简单的 .tiff
图片并进行了测试:
static Image n;
public static void main(String[] args) {
JFrame f = new JFrame();
JPanel p = new JPanel() {
@Override
public void paintComponent(Graphics graphics) {
graphics.drawImage(n, 0, 0, null);
}
}
f.add(p);
n = Toolkit.getDefaultToolkit().getImage(("/Users/zinedine/Desktop/test_image.tiff");
f.setVisible(true)
}
它什么也没产生:
我再次尝试:这次,将图像添加到我的 java 项目的基础文件夹中,并将其作为字符串输入:"NSImage://test_image.tiff"
。就像我所做的一切一样,它不起作用。
但是,如果我将我喜欢的路径字符串更改为 NSImage,例如 "NSImage://NSApplicationIcon"
...
有效。我快速搜索了 NSImage,找到了一个。看起来这些图像的文件类型是 .png
。这有点令人不安,因为我希望从中得到一个合适的图像。请注意,我也有点期待它:如果它期待 "NSImage://something"
形式的参数,那么它可能会忽略其他任何东西。
显然,我有几个问题:
Toolkit如何加载图片?如果我尝试从我的桌面加载 .tiff
图像,这就是我调用 .toString()
:
时得到的结果
sun.awt.image.ToolkitImage@25f38edc // Also can't be cast to java.awt.BufferedImage
读者(和作者,如果有的话)是 public API 的一部分吗?换句话说,我可以调用一些东西来将我的 .tiff
文件加载到 Image
中(然后我可以将其转换为 `BufferedImage?
再一次,如果 readers/writers 是 API 的一部分,为什么 javax.imageio
包找不到它们?
这可能看起来很少,(是的,很抱歉在这个问题上毁了你的一天),但对我来说,这看起来像预期的那样,但同时也是错误的行为。奖励标记:是否有任何友好的(即开源)成像 api(不是 JAI)可以处理 .tiff
文件(和其他)?
您在这里提出了多个问题,但我会尽力解释所有问题。 :-)
使用 Toolkit
加载图像(java.awt.Image
和朋友)是 "old" 异步 producer/consumer 图像 API 的一部分,可能会感觉有点尴尬的工作。加载打包的图标和类似的东西完全没问题,但不太适合加载用户提供的大型图像,因为你没有进度跟踪,如果出现问题则很少有错误反馈等。
如果您想执行任何类型的图像处理,这些图像也比 BufferedImage
s 有用得多。您不能将它们转换为 BufferedImage
,但您可以 "convert" 它们,方法是将它们绘制到 BufferedImage
.
Toolkit
class是抽象的,你用Toolkit.getToolkit()
得到一个具体的实例。这个具体实例是特定于平台的,并且最终使用系统特定的本机调用来调用大多数方法,例如加载图像。
Apple Java 实现确实有一些额外的功能,比如允许您使用特殊的 URI 方案加载 Apple 系统图像。它似乎也可以通过这种方式加载捆绑图像,使用 @2x
命名约定,甚至 OS X 中的多尺度 TIFF 或可缩放 PDF 用于您的应用程序的分辨率独立图形。
请注意,要使其正常工作,您需要将应用程序打包为应用程序包,并将图像放在包的资源文件夹(即 Contents/Resources
)中。并且您必须使用其基本名称引用图像,不带扩展名。据我所知,您不能使用此功能来读取未与您的应用程序一起打包的随机 TIFF 文件(即用户提供的内容)。
此外,此功能特定于 Apple JRE,并且仅适用于 Apple 自己的 JRE 和 OS X。它不是 public Java API 的一部分,它不能跨平台工作。我建议谨慎使用该功能,并且只是为了在 OS X 上获得更好的系统集成(即让您的应用程序看起来更原生)。
要读取(和写入)任何 TIFF(或任何其他格式),您应该改用 ImageIO
和一些适当的插件。由于某些原因,JRE 没有附带 TIFF 格式的插件,但存在几个第三方插件。
如果您不想使用 JAI(通过 jai_imageio.jar
),我可以推荐我自己的 TwelveMonkeys library which supports TIFF 以及许多其他格式。它使用商业友好的开源 BSD 许可证。
还有 Apache Commons Imaging, iCafe 和可能其他可以 read/write TIFF 的,但它们有自己的自定义 APIs,这使得它们不太灵活并且更专有 IMO。
我一直在阅读 OS X Java 开发人员工具,以帮助使我的应用程序更 "native" 与操作系统兼容。我在这个特定的 section 中发现了一些有趣的东西。 (强调我的)
To load a resolution-independent tiff, icns, or pdf file from the Resources folder of your application bundle into your Java application, use the
getImage()
method ofjava.awt.Toolkit
. The string you pass intogetImage()
is of the form"NSImage://MyImage"
. Do not include the file extension of the image. Also be aware that the Sun 2D renderer is disabled when the user interface scale factor does not have a value of 1.0. Use the Quartz renderer so that your images scale smoothly.
熟悉 javax.imageio
,这完全出乎我的意料,因为我不知道有任何其他方法可以将其他文件类型加载到图像中。特别是在一个过时的平台上,并且绝对不支持 .tiff
等文件。例如,在我的计算机上进行快速测试会得到以下结果:
Supported read formats: [jpg, bmp, gif, png, wbmp, jpeg]
Supported write formats: [jpg, bmp, gif, png, wbmp, jpeg]
'JPEG' reader: com.sun.imageio.plugins.jpeg.JPEGImageReader@5e9f23b4
'JPEG' reader: com.sun.imageio.plugins.jpeg.JPEGImageWriter@378fd1ac
我尝试加载一个简单的 .tiff
图片并进行了测试:
static Image n; public static void main(String[] args) { JFrame f = new JFrame(); JPanel p = new JPanel() { @Override public void paintComponent(Graphics graphics) { graphics.drawImage(n, 0, 0, null); } } f.add(p); n = Toolkit.getDefaultToolkit().getImage(("/Users/zinedine/Desktop/test_image.tiff"); f.setVisible(true) }
它什么也没产生:
我再次尝试:这次,将图像添加到我的 java 项目的基础文件夹中,并将其作为字符串输入:"NSImage://test_image.tiff"
。就像我所做的一切一样,它不起作用。
但是,如果我将我喜欢的路径字符串更改为 NSImage,例如 "NSImage://NSApplicationIcon"
...
有效。我快速搜索了 NSImage,找到了一个。看起来这些图像的文件类型是 .png
。这有点令人不安,因为我希望从中得到一个合适的图像。请注意,我也有点期待它:如果它期待 "NSImage://something"
形式的参数,那么它可能会忽略其他任何东西。
显然,我有几个问题:
Toolkit如何加载图片?如果我尝试从我的桌面加载
时得到的结果.tiff
图像,这就是我调用.toString()
:sun.awt.image.ToolkitImage@25f38edc // Also can't be cast to java.awt.BufferedImage
读者(和作者,如果有的话)是 public API 的一部分吗?换句话说,我可以调用一些东西来将我的
.tiff
文件加载到Image
中(然后我可以将其转换为 `BufferedImage?再一次,如果 readers/writers 是 API 的一部分,为什么
javax.imageio
包找不到它们?
这可能看起来很少,(是的,很抱歉在这个问题上毁了你的一天),但对我来说,这看起来像预期的那样,但同时也是错误的行为。奖励标记:是否有任何友好的(即开源)成像 api(不是 JAI)可以处理 .tiff
文件(和其他)?
您在这里提出了多个问题,但我会尽力解释所有问题。 :-)
使用 Toolkit
加载图像(java.awt.Image
和朋友)是 "old" 异步 producer/consumer 图像 API 的一部分,可能会感觉有点尴尬的工作。加载打包的图标和类似的东西完全没问题,但不太适合加载用户提供的大型图像,因为你没有进度跟踪,如果出现问题则很少有错误反馈等。
如果您想执行任何类型的图像处理,这些图像也比 BufferedImage
s 有用得多。您不能将它们转换为 BufferedImage
,但您可以 "convert" 它们,方法是将它们绘制到 BufferedImage
.
Toolkit
class是抽象的,你用Toolkit.getToolkit()
得到一个具体的实例。这个具体实例是特定于平台的,并且最终使用系统特定的本机调用来调用大多数方法,例如加载图像。
Apple Java 实现确实有一些额外的功能,比如允许您使用特殊的 URI 方案加载 Apple 系统图像。它似乎也可以通过这种方式加载捆绑图像,使用 @2x
命名约定,甚至 OS X 中的多尺度 TIFF 或可缩放 PDF 用于您的应用程序的分辨率独立图形。
请注意,要使其正常工作,您需要将应用程序打包为应用程序包,并将图像放在包的资源文件夹(即 Contents/Resources
)中。并且您必须使用其基本名称引用图像,不带扩展名。据我所知,您不能使用此功能来读取未与您的应用程序一起打包的随机 TIFF 文件(即用户提供的内容)。
此外,此功能特定于 Apple JRE,并且仅适用于 Apple 自己的 JRE 和 OS X。它不是 public Java API 的一部分,它不能跨平台工作。我建议谨慎使用该功能,并且只是为了在 OS X 上获得更好的系统集成(即让您的应用程序看起来更原生)。
要读取(和写入)任何 TIFF(或任何其他格式),您应该改用 ImageIO
和一些适当的插件。由于某些原因,JRE 没有附带 TIFF 格式的插件,但存在几个第三方插件。
如果您不想使用 JAI(通过 jai_imageio.jar
),我可以推荐我自己的 TwelveMonkeys library which supports TIFF 以及许多其他格式。它使用商业友好的开源 BSD 许可证。
还有 Apache Commons Imaging, iCafe 和可能其他可以 read/write TIFF 的,但它们有自己的自定义 APIs,这使得它们不太灵活并且更专有 IMO。