Xcode @2x 图像后缀在 iOS 中未显示为 Retina
Xcode @2x image suffix not showing as Retina in iOS
我在处理视网膜图像时遇到困难。
下面的屏幕截图显示了 UICollectionView
,每个 UICollectionViewCell
中都包含一个 UIImageView
。
在应用程序中,我有一张名为 travel.png 的 512x512 像素的大图像。
绿色圆圈显示了我命名此文件时应用程序上显示的内容:travel.png。蓝色圆圈显示了我将图像名称更新为 travel@2x.png(即视网膜命名)时看到的内容。
我希望由于图像尺寸较大 (512x512),只需添加 @2x 后缀就足以将其转换为清晰度的两倍(即视网膜),但正如您从两个屏幕截图中看到的那样,两个版本图像都显示为非视网膜图像。
如何更新图像以使其在 Retina 中显示?
travel.png:
旅行@2x.png:
* 已更新 *
在下面的评论中提出以下要求:
我通过调用以下函数加载此图像:
// Note - when this method is called: contentMode is set to .scaleAspectFit & imageName is "travel"
public func setImageName(imageName: String, contentMode: ContentMode) {
self.contentMode = contentMode
if let image = UIImage(named: imageName) {
self.image = image
}
}
以下是图像在应用程序呈现之前在 Xcode 中的显示方式(如您所见,它的清晰度足够高):
我已经解决了@DarshanKunjadiya 问题。
确保(如果您已经在使用资产):
- 确保图像未被取消分配
- 现在可以在不带扩展名的故事板或代码中使用图像。 (例如 "image" 不是 "image.png")
如果您不使用资产中的图像,请将它们移至资产。
希望对您有所帮助。
让我知道您的反馈。
我认为没有 @2x
和 @3x
的图像是为低分辨率设备(如 iphone 4 和 3G)呈现的。
我认为的解决方案是始终使用 .xcassets
文件或在图像名称中添加 @2x or @3X
。
在iOS中,内容基于iOS坐标系放置在屏幕上。为了在具有 1:1 像素密度的标准分辨率系统上显示图像,我们应该以@1x 分辨率提供图像。对于更高分辨率的显示器,像素密度将是比例因子 2.0、3.0,在 iOS 系统中分别表示为 @2x 和 @3x。也就是说,高分辨率显示器需要更高密度的图像。
例如,如果要以标准分辨率显示尺寸为 128x128 的图像。您必须提供相同尺寸的@2x 和@3x 图像。即,@2x 版本为 256x256,@3x 版本为 384x384 图像。
在下面的屏幕截图中,我为 2x 版本提供了尺寸为 256x256 的图像,以便在 iPhone 6 秒内显示 128x128 像素的图像。 iPhone 6 秒以@2x 大小渲染图像。将 1x、2x 和 3x 三个版本的图像与资产目录一起使用将解决您的问题。因此 iPhone 将自动使用屏幕分辨率自动渲染正确大小的图像。
如果您打算只为所有尺寸制作一张图片,我建议您使用 Assets.xcassets
。在这里创建文件夹结构和管理媒体资产很容易。
步骤
- 单击
+
图标后,您将显示一个操作列表。选择创建一个New folder
。
- 选择创建的新文件夹,再次单击
+
图标并单击 New Image Set
。
- 选择图像集。并选择属性检查器。
- Select
Single Scale
,在 Scales
下。
- 拖放图像。
- 根据需要重命名图像名称和文件夹名称。
现在您可以使用所有屏幕尺寸的图像名称使用此图像。
您看到低质量图像的原因是 anti-aliasing。当您提供比 UIImageView 的实际框架更大的图像(scaleAspectFit 模式)时,系统将自动缩小它们。在缩放期间,可以在曲线形状处添加一些抗锯齿效果。为避免这种效果,您应该提供要在屏幕上显示的确切图像尺寸。
要检测 UIImageView 是否自动缩放图像,您可以在模拟器菜单中打开“调试”->“颜色未对齐图像”:
现在所有缩放后的图像都会在模拟器中以黄色突出显示。每个突出显示的图像都可能具有抗锯齿效果并影响 CPU 缩放算法的使用:
要解决此问题,您应该使用精确尺寸。所以系统会直接使用它们而不需要任何额外的计算。例如,如果您的按钮尺寸为 80x80px,则您应该添加三张图像以声明目录,尺寸和 dpi 如下:80x80px (72 dpi)、160x160px (144 dpi) 和 240x240px (216 dpi):
现在将在屏幕上绘制图像而不会缩小尺寸,视觉质量更好:
TL;DR;
将视图层的 minificationFilter
更改为 .trilinear
imageView.layer.minificationFilter = .trilinear
如下面的设备截图所示
正如 Anton 的回答正确指出的那样,您观察到的混叠效果是由于源图像和显示它的图像视图之间的尺寸差异很大造成的。添加 @2x
后缀不会改变任何东西如果您不更改源图像本身的尺寸。
那是说有一种简单的方法可以在不调整原始图像大小的情况下改善这种情况:CALayer
提供了对图形后端用于调整图像大小的方法的一些控制:minificationFilter
and magnificationFilter
. The first one is relevant in your case since the image size is being reduced. The default value is CALayerContentsFilter.linear
, just switch to .trilinear
for a much better result (more info on those wikipedia pages) .这将需要更多的 GPU 功率(因此电池),尤其是当您将它应用于许多图像时。
您应该真正考虑在显示图像之前调整图像大小,无论是静态还是在 运行 时(并且可能缓存调整大小的版本)。除了视觉质量差之外,在 UI 中大量使用如此大的图像会降低性能并浪费大量内存,从而导致其他潜在问题。
我在处理视网膜图像时遇到困难。
下面的屏幕截图显示了 UICollectionView
,每个 UICollectionViewCell
中都包含一个 UIImageView
。
在应用程序中,我有一张名为 travel.png 的 512x512 像素的大图像。 绿色圆圈显示了我命名此文件时应用程序上显示的内容:travel.png。蓝色圆圈显示了我将图像名称更新为 travel@2x.png(即视网膜命名)时看到的内容。
我希望由于图像尺寸较大 (512x512),只需添加 @2x 后缀就足以将其转换为清晰度的两倍(即视网膜),但正如您从两个屏幕截图中看到的那样,两个版本图像都显示为非视网膜图像。
如何更新图像以使其在 Retina 中显示?
travel.png:
旅行@2x.png:
我通过调用以下函数加载此图像:
// Note - when this method is called: contentMode is set to .scaleAspectFit & imageName is "travel"
public func setImageName(imageName: String, contentMode: ContentMode) {
self.contentMode = contentMode
if let image = UIImage(named: imageName) {
self.image = image
}
}
以下是图像在应用程序呈现之前在 Xcode 中的显示方式(如您所见,它的清晰度足够高):
我已经解决了@DarshanKunjadiya 问题。 确保(如果您已经在使用资产):
- 确保图像未被取消分配
- 现在可以在不带扩展名的故事板或代码中使用图像。 (例如 "image" 不是 "image.png")
如果您不使用资产中的图像,请将它们移至资产。
希望对您有所帮助。 让我知道您的反馈。
我认为没有 @2x
和 @3x
的图像是为低分辨率设备(如 iphone 4 和 3G)呈现的。
我认为的解决方案是始终使用 .xcassets
文件或在图像名称中添加 @2x or @3X
。
在iOS中,内容基于iOS坐标系放置在屏幕上。为了在具有 1:1 像素密度的标准分辨率系统上显示图像,我们应该以@1x 分辨率提供图像。对于更高分辨率的显示器,像素密度将是比例因子 2.0、3.0,在 iOS 系统中分别表示为 @2x 和 @3x。也就是说,高分辨率显示器需要更高密度的图像。
例如,如果要以标准分辨率显示尺寸为 128x128 的图像。您必须提供相同尺寸的@2x 和@3x 图像。即,@2x 版本为 256x256,@3x 版本为 384x384 图像。
在下面的屏幕截图中,我为 2x 版本提供了尺寸为 256x256 的图像,以便在 iPhone 6 秒内显示 128x128 像素的图像。 iPhone 6 秒以@2x 大小渲染图像。将 1x、2x 和 3x 三个版本的图像与资产目录一起使用将解决您的问题。因此 iPhone 将自动使用屏幕分辨率自动渲染正确大小的图像。
如果您打算只为所有尺寸制作一张图片,我建议您使用 Assets.xcassets
。在这里创建文件夹结构和管理媒体资产很容易。
步骤
- 单击
+
图标后,您将显示一个操作列表。选择创建一个New folder
。 - 选择创建的新文件夹,再次单击
+
图标并单击New Image Set
。 - 选择图像集。并选择属性检查器。
- Select
Single Scale
,在Scales
下。 - 拖放图像。
- 根据需要重命名图像名称和文件夹名称。 现在您可以使用所有屏幕尺寸的图像名称使用此图像。
您看到低质量图像的原因是 anti-aliasing。当您提供比 UIImageView 的实际框架更大的图像(scaleAspectFit 模式)时,系统将自动缩小它们。在缩放期间,可以在曲线形状处添加一些抗锯齿效果。为避免这种效果,您应该提供要在屏幕上显示的确切图像尺寸。
要检测 UIImageView 是否自动缩放图像,您可以在模拟器菜单中打开“调试”->“颜色未对齐图像”:
现在所有缩放后的图像都会在模拟器中以黄色突出显示。每个突出显示的图像都可能具有抗锯齿效果并影响 CPU 缩放算法的使用:
要解决此问题,您应该使用精确尺寸。所以系统会直接使用它们而不需要任何额外的计算。例如,如果您的按钮尺寸为 80x80px,则您应该添加三张图像以声明目录,尺寸和 dpi 如下:80x80px (72 dpi)、160x160px (144 dpi) 和 240x240px (216 dpi):
现在将在屏幕上绘制图像而不会缩小尺寸,视觉质量更好:
TL;DR;
将视图层的 minificationFilter
更改为 .trilinear
imageView.layer.minificationFilter = .trilinear
如下面的设备截图所示
正如 Anton 的回答正确指出的那样,您观察到的混叠效果是由于源图像和显示它的图像视图之间的尺寸差异很大造成的。添加 @2x
后缀不会改变任何东西如果您不更改源图像本身的尺寸。
那是说有一种简单的方法可以在不调整原始图像大小的情况下改善这种情况:CALayer
提供了对图形后端用于调整图像大小的方法的一些控制:minificationFilter
and magnificationFilter
. The first one is relevant in your case since the image size is being reduced. The default value is CALayerContentsFilter.linear
, just switch to .trilinear
for a much better result (more info on those wikipedia pages) .这将需要更多的 GPU 功率(因此电池),尤其是当您将它应用于许多图像时。
您应该真正考虑在显示图像之前调整图像大小,无论是静态还是在 运行 时(并且可能缓存调整大小的版本)。除了视觉质量差之外,在 UI 中大量使用如此大的图像会降低性能并浪费大量内存,从而导致其他潜在问题。