什么会导致彩色 mac 应用程序图标显示为灰度?

What could cause a colored mac app icon to be displayed as grayscale?

注:最后是MCVE

我更新了 mac 应用程序的 AppIcon 和文档图标。图标已更改,但它们也显示为灰度。源文件 (PNG) 是彩色的。图标在 Xcode 中显示为彩色,但在上下文中(停靠栏中的 AppIcon 和 Finder 中的文档图标)是灰度的。我尝试了一些明显的方法,例如清理构建文件夹、重新启动 Xcode 和重新启动 Finder,但我不知道还能尝试什么。

这是图标在上下文中的显示方式:

Xcode中的图标是这样的:

我所做的只是更新了一些 PNG!一切仍然正常运行。该应用程序仍会启动,双击文档会打开该应用程序。问题是图标是灰色的。


在更改图标的 git 提交中,唯一更改的是一些 PNG 和一些文档文件(README 中的 link、屏幕截图和其他一些内容)。如果我在更改图标之前检查提交,一切都很好。如果我检查更改图标的提交,它们是灰色的。

我一直在查看 PNG 本身以试图弄清楚这一点。我正在使用 pngcheck 检查文件。

旧(有效)16x16 图标:

chunk IHDR at offset 0x0000c, length 13
  16 x 16 image, 32-bit RGB+alpha, non-interlaced
chunk bKGD at offset 0x00025, length 6
  red = 0x00ff, green = 0x00ff, blue = 0x00ff
chunk IDAT at offset 0x00037, length 142
  zlib: deflated, 2K window, maximum compression
  row filters (0 none, 1 sub, 2 up, 3 avg, 4 paeth):
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 (16 out of 16)
chunk IEND at offset 0x000d1, length 0

新的(损坏的)16x16 图标:

chunk IHDR at offset 0x0000c, length 13
  16 x 16 image, 32-bit RGB+alpha, non-interlaced
chunk IDAT at offset 0x00025, length 109
  zlib: deflated, 2K window, default compression
  row filters (0 none, 1 sub, 2 up, 3 avg, 4 paeth):
    0 1 1 1 2 2 4 1 1 4 2 2 1 1 0 0 (16 out of 16)
chunk IEND at offset 0x0009e, length 0

好的,也许 bKGD 块是必需的?没有。我通过 gm convert(没有参数)传递图像,它添加了 bKGD 并更改了压缩级别,它仍然以灰度显示。

gm 转换后的新(损坏)16x16 图标:

chunk IHDR at offset 0x0000c, length 13
  16 x 16 image, 32-bit RGB+alpha, non-interlaced
chunk bKGD at offset 0x00025, length 6
  red = 0x00ff, green = 0x00ff, blue = 0x00ff
chunk IDAT at offset 0x00037, length 106
  zlib: deflated, 2K window, maximum compression
  row filters (0 none, 1 sub, 2 up, 3 avg, 4 paeth):
    0 1 1 1 2 2 4 1 1 4 2 2 1 1 0 0 (16 out of 16)
chunk IEND at offset 0x000ad, length 0

所以现在看起来损坏的 PNG 和工作的 PNG 之间的唯一区别是行过滤器(当然还有图像数据本身)。为什么这会引起问题?!我不知道单独使用命令行设置行过滤器的方法。这甚至可能与 libpng 相关吗?每当我使用 libpng 时,我只是让图书馆选择过滤器。我是否必须编写自己的 png 编码器来解决这个问题?

我觉得我一定是找错了树,但是 唯一改变的(影响构建的)是少数 PNG 文件。这太疯狂了。


我又试了一下,发现 128@2x 图标(不是 256 图标!)才是最重要的。用旧图标替换此图像会导致旧图标以彩色显示。用新图标替换此图像会使新图标以灰度显示。这两个 PNG 文件之间的区别是导致问题的原因。这是我遇到过最可笑的问题。

我正在尝试将这些图像靠得更近,以尝试使新图像正常工作或使旧图像失效,但我就是想不通。我通过用于制作新图像的同一工具传递了旧图像(恰好是该图标所针对的应用程序!)并且它仍然以颜色显示!这是 pngcheck 输出。

动画之后的旧(工作)128x128@2x 图标:

chunk IHDR at offset 0x0000c, length 13
  256 x 256 image, 32-bit RGB+alpha, non-interlaced
chunk IDAT at offset 0x00025, length 965
  zlib: deflated, 32K window, default compression
  row filters (0 none, 1 sub, 2 up, 3 avg, 4 paeth):
    1 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
    2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2
    2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2
    2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 2 2 2
    2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 2
    2 2 2 4 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 4 2 2 2 2 2
    2 2 4 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
    2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
    1 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 (256 out of 256)
chunk IEND at offset 0x003f6, length 0

动画后的新(损坏)128x128@2x 图标:

chunk IHDR at offset 0x0000c, length 13
  256 x 256 image, 32-bit RGB+alpha, non-interlaced
chunk IDAT at offset 0x00025, length 830
  zlib: deflated, 32K window, default compression
  row filters (0 none, 1 sub, 2 up, 3 avg, 4 paeth):
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 2 2 2 2 2 2
    2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2
    2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
    2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 2 2 2
    2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2
    2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 2 2 2 2 2
    2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
    2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2
    2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 (256 out of 256)
chunk IEND at offset 0x0036f, length 0

这太荒谬了!我开始怀疑我是否在 macOS.

中发现了一个非常奇怪的错误

如果您想自己检查图像,这些是上一节中的两张图像。我认为 imgur 重新编码图像,所以我将它们转换为数据 URI,这样你就可以将它们粘贴到 URL 栏并下载它们。

动画之后的旧(工作)128x128@2x 图标:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAADxUlEQVR4nO3dQW6kMBRAQRjl/ldmbgALx7KdV7XNIg7debL0DdzPdd3Xi/u6nrefA+f6t3oBwDoCAGECAGECAGECAGECAGECAAAAAAAAAAAAAAAAAAAAAAAbeX0nAOs9h7+X4fYd25onAkGYAECYAECYAECYAECYAECYAECYGe1kp8/xV3OOYC47AAgTAAgTAAgTAAgTAAgTAAgTAAgzYx1kzr+WcwJj7AAgTAAgTAAgTAAgTAAgTAAgTAAgzAz1gzn/2ZwTeGcHAGECAGECAGECAGECAGECAGECAGECAGECAGECAGECAGECAGECAGECAGECAGH5e6Xd799Wf16AHQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCECQCE/axewHTP9axewpDj316//eX/WOB9/Cfwxg4AwgQAwgQAwgQAwgQAwgQAwgQAwvafcU6e428/pR41/An/7Ss0/x9g73MEdgAQJgAQJgAQJgAQJgAQJgAQJgAQtn5Gufn9+lsv7jfcf/svXP8F/7L2nIAdAIQJAIQJAIQJAIQJAIQJAIQJAITNn0FuPuf/cvTir+sa/gv2H6S/Onz51+xzAnYAECYAECYAECYAECYAECYAECYAEPazegG7+xrCnn9O4Gznz/nXsgOAMAGAMAGAMAGAMAGAMAGAMAGAsPEx6uH3+882/+IsvvyTB/Hm/F/GnhdgBwBhAgBhAgBhAgBhAgBhAgBhAgBhngcw2egc+/RDFub4e7MDgDABgDABgDABgDABgDABgDABgDDnADZnjs5MdgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQNv/188/1TP8dvBi8/PO/Iby6p34CdgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQtv5ub88LWOt2+deae7//FzsACBMACBMACBMACBMACBMACBMACFt/DuCLcwJj7tHP+HH9h6yd83+xA4AwAYAwAYAwAYAwAYAwAYAwAYCwrWeUv+L0cwTDc/zVTj9HsPccf5QdAIQJAIQJAIQJAIQJAIQJAIQJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvPgPQZExnSU6E9oAAAAASUVORK5CYII=

动画后的新(损坏)128x128@2x 图标:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAADPklEQVR4nO3cwZEDIQwAQbhy/injDO7DQ6amOwJ5dz3FR6wFAAAAAAAAAAAAAAAAAAAA/Jo9PUDdWetMzzBp+wZH/U0PAMwRAAgTAAgTAAgTAAgTAAgTAAgTAAgTAAgTAAgTAAgTAAgTAAgTAAgTAAizi32pvs8/zX0Cd5wAIEwAIEwAIEwAIEwAIEwAIEwAIEwAIEwAIEwAIEwAIEwAIEwAIEwAIEwAICy/S22fv61+n4ATAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIQJAIR9pge4dtaZHmHUnh7g+cd/+QP2+Bu44QQAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYfO7zI/v8z89/Fpr7bd/wfwHfGv2PgEnAAgTAAgTAAgTAAgTAAgTAAgTAAgTAAgTAAgTAAgTAAgTAAgTAAgTAAgTAAi730V+fJ9/2v3DG378l1/Q+/v80+7uE3ACgDABgDABgDABgDABgDABgDABgDABgDABgDABgDABgDABgDABgDABgDABgLDP9AB19uGZ5AQAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYQIAYXt6gHXWmR4hbXv8s/bof9AJAMIEAMIEAMIEAMIEAMIEAMIEAMIEAMIEAMIEAMIEAMIEAMIEAMIEAMIEAMLm7wO4Vb9PYE+/w9N+/sP7/LecACBMACBMACBMACBMACBMACBMACBMACBMACBMACBMACBMACBMACBMACBMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4B9fjX8anopwslQAAAAASUVORK5CYII=

我真的希望有人能解决这个问题!


我已经创建了这个问题的 MCVE(在 github 上)。我创建了一个新的 mac 应用程序。我所做的只是设置 128@2x 图标,我能够重现这个问题。 "working" 图标是彩色的。 "broken" 图标是灰色的(请参阅上一节中的数据 URI)。您可以编辑 Contents.json 文件中的文件名(然后是干净的构建)以在它们之间切换。我似乎开始在 macOS 中发现错误!虽然,如果它是一个错误,那么它可能不会在 Mojave 中得到修复。


我向 Apple 发送了错误报告。我仍然想要解决此问题的方法,因为我找不到解决方法。

问题可以在 Xcode 11.3.1 的 macOS Catalina 上重现。

缩小问题范围

资产目录 (.xcassets) 由 Xcode 编译为 Asset.car 文件。

要查看已编译的 Asset.car 甚至从中提取图像资源,您需要一个额外的工具,例如资产目录修补匠

可以通过以下方式安装此工具:

brew cask install asset-catalog-tinkerer 

使用该工具可以从 Asset.car 中提取图像。它被命名为 256_broken_Normal@2x.png 并且它是一个灰度图像。

可以通过视觉或命令行调用来检查:

sips -g all 256_broken_Normal@2x.png    

该工具的输出是:

/Users/stephan/tmp/256_broken_Normal@2x.png
  pixelWidth: 256
  pixelHeight: 256
  typeIdentifier: public.png
  format: png
  formatOptions: default
  dpiWidth: 72.000
  dpiHeight: 72.000
  samplesPerPixel: 2
  bitsPerSample: 8
  hasAlpha: yes
  space: Gray
  profile: Generic Gray Gamma 2.2 Profile

所以你可以看到它不再是 RGBA32 而是带有 alpha 通道的灰度图像(参见 samplesPerPixel、hasAlpha 和 color space 属性)。

第一个结果

所以这可能不是 macOS 中的错误,而是 Asset.car 文件的创建。

内容分析一

有趣的是,您不能通过删除并重新添加颜色配置文件来解决问题,也不能通过将图像加载到图像处理器并重写它来解决问题。

难道是图片的像素内容值?

接下来尝试:将图片编辑软件红色区域的单个像素从#0xff0000ff 更改为#0xff0100ff。所以这是人眼在视觉上应该看不到的变化,但是在这种情况下你可以看到:图像不再是灰度,而是彩色的。

让我们进一步分析颜色,有趣的是:4 个通道中的每个值都有值 0x00 或 0xff,这给出了 16 种不同的组合。

创建随机图像

这听起来像是一个线索。所以接下来尝试:创建一个随机使用 8 种可能的不透明颜色之一的小程序(每个 rgb 通道 0x00 或 0xff 的所有组合,alpha = 0xff)。

结果是彩色图像。

内容分析二

我们再看一下图片。难道是颜色分布均匀?

现在让我们用一个小程序来分析一下,统计R G B A值0xff出现的频率,结果是:

   R     G      B      A
212992 212992 212992 540672

确实是0xff值的R、G、B出现在同一个数上

假设

为了进一步证实这一假设,现在可以通过编程生成条纹图案,其中颜色出现的频率相同。

事实上,通过这张图片,我们在 Dock 和 App Switcher 中看到了一个灰度图像,在屏幕截图中看到了背景中的资产和灰度应用程序图标,当通过 CMD+TAB 在前景。

现在我们再次尝试半随机分布相同颜色的小方块。同样,在 Xcode 中使用该图像时,我们会得到一个灰度应用程序图标,请参见屏幕截图。

测试

每当更改图像时,您在 Xcode 中要做的第一件事就是 (SHIFT-CMD-K)。

如果有人想自己测试一下,这里是图片:

https://www.software7.biz/iertzzlmbkjdkjrk/256_randomWorking.png(工作 -> 颜色) https://www.software7.biz/iertzzlmbkjdkjrk/256_brokenStripes.png(损坏 -> 灰度) https://www.software7.biz/iertzzlmbkjdkjrk/256_semiRandomBroken.png(博肯 -> 灰度)

总结

所以它似乎不是 macOS 中的错误,而是在将资产 compilation/optimization 放入 Asset.car 文件期间。当等于0xff 的R,G,B 值的个数相同时,似乎会发生这种情况。可能还有其他情况。

一个简单的解决方法似乎是简单地稍微改变一个像素的值。这是肉眼看不到的。