Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Note: MCVE at the end

I updated the AppIcon and Document icon for my mac app. The icons have changed but they also show as grayscale. The sources files (PNGs) are colored. The icons appear colored inside Xcode but in context (AppIcon in the dock and Document icons in Finder) are grayscale. I've tried the obvious stuff like cleaning the build folder, relaunching Xcode and relaunching Finder but I don't know what else to try.

This is how the icons appear in context:

Icon in the dock Icon on desktop

This is how the icons appear in Xcode:

Icon in Xcode

All I did was update some PNGs! Everything still functions correctly. The app still launches and double clicking on a document opens the application. The problem is that the icons are gray.


In the git commit that changes the icons, the only things that change are some PNGs and a few documentation files (a link in the README, a screenshot and some other stuff). If I checkout the commit before changing the icons, everything is fine. If I checkout the commit that changes the icons, they're gray.

I've been looking at the PNGs themselves to try to figure this out. I'm using pngcheck to inspect the files.

Old (working) 16x16 icon:

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

New (broken) 16x16 icon:

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

Ok, so maybe the bKGD chunk is required? Nope. I passed the image through gm convert (with no arguments) which adds the bKGD and also changes the compression level and it's still being displayed in grayscale.

New (broken) 16x16 icon after gm convert:

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

So now it looks like the only difference between the broken PNGs and the working ones are the row filters (and of course the image data itself). WHY ON EARTH WOULD THIS CAUSE A PROBLEM?! I'm not aware of a way to set the row filters using the command line alone. Is this even possible to do with libpng? Whenever I use libpng, I just let the library choose the filters. Would I have to write my own png encoder to solve this?

I feel like I must be barking up the wrong tree here but the only thing that changed (that affects the build) are a handful of PNG files. This is insane.


I played around with this some more and found that the 128@2x icon (not the 256 icon!) is the one that matters. Replacing this image with the old icon causes the old icon to be shown in color. Replacing this image with the new icon cases the new icon to be shown in grayscale. The difference between these two PNG files is what's causing the issue. This is the most ridiculous problem that I've ever encountered.

I'm trying to bring these images closer together to try to make the new one work or the old one break but I just can't figure it out. I passed the old image through the same tool that I used to make the new image (which happens to be the application for which this icon is for!) AND IT STILL SHOWS UP IN COLOR! Here's the pngcheck output.

Old (working) 128x128@2x icon after animera:

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

New (broken) 128x128@2x icon after animera:

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

This is ridiculous! I'm beginning to wonder if I've found a very strange bug in macOS.


In case you want to inspect the images yourself, these are the two images from the previous section. I think imgur re-encodes images so I converted them to data URIs so you can paste them into the URL bar and download them.

Old (working) 128x128@2x icon after animera:

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=

New (broken) 128x128@2x icon after animera:

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=

I really hope someone can figure this out!


I have created a MCVE of this problem (on github). I created a new mac app. All I did was set the 128@2x icon and I'm able to reproduce this problem. The "working" icon is in color. The "broken" icon is gray (see the data URIs from the previous section). You can edit the filename in the Contents.json file (followed by a clean build) to switch between them. It's beginning to seem like I've found a bug in macOS! Although, if it is a bug then it probably won't be fixed in Mojave.


I sent a bug report to Apple. I would still like a workaround for this as I haven't been able to find one.

like image 778
Indiana Kernick Avatar asked Mar 28 '20 02:03

Indiana Kernick


1 Answers

The problem can be reproduced on macOS Catalina with Xcode 11.3.1.

Narrowing down the problem

The asset catalog (.xcassets) is compiled by Xcode to an Asset.car file.

To take a look into the compiled Asset.car and even extract an image resource from it, you would need an additional tool, e.g. the Asset Catalog Tinkerer.

Installation of this tool can be achieved by:

brew cask install asset-catalog-tinkerer 

With the tool the image can be extracted from the Asset.car. It's named [email protected] and it is a grayscale image.

One can check this visually or with the command line call:

sips -g all [email protected]    

The output of the tool is:

/Users/stephan/tmp/[email protected]
  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

So you can see that it is no longer RGBA32 but a grayscale image with alpha channel (see samplesPerPixel, hasAlpha and color space properties).

First Result

So this probably isn't a bug in macOS, but rather the creation of the Asset.car file.

Content Analysis I

Interestingly, you can't fix the problem by removing and re-adding color profiles, nor by loading the image into an image processor and rewriting it.

So could it be the pixel content values of the image?

Next try: change a single pixel in the red area of the image editing software from #0xff0000ff to #0xff0100ff. So this is a change that the human eye should not be able to see visually, but in this case you can see it: the image is no longer grayscale, but colored.

Let's analyze the colors further and interessting: each value in the 4 channels has either the value 0x00 or 0xff which gives 16 different combinations.

Create Random Image

That sounds like a lead. So next try: Create a small program that randomly uses one of the 8 possible opaque colors (all combinations of 0x00 or 0xff per rgb channel, alpha = 0xff).

The outcome is a color image.

Content Analysis II

Let's look at the picture again. Could it be that the colors are evenly distributed?

Now let us analyze with a small program that counts how often the R G B A values 0xff occur, the result is:

   R     G      B      A
212992 212992 212992 540672

It is indeed the case that the R, G and B with the value 0xff occur in exactly the same number.

Hypothesis

To further substantiate this hypothesis, one can now programmatically generate a stripe pattern in which the colors occur equally often.

And indeed, with this image we see a grayscale image in the Dock and in the App Switcher, see in the screenshot the assets in the background and the grayscale app icon when using the App Switcher via CMD+TAB in the foreground.

stripe pattern

Now we make another attempt with a semi-random distribution of small squares of the same color. And again, when using that image in Xcode we get a grayscale app icon, see screenshot.

semi-random image

Test

Whenever changing the image, the first thing you have to do in Xcode is a <Product/Clean Build Folder> (SHIFT-CMD-K).

If one would like to test that on your own, here are the images:

https://www.software7.biz/iertzzlmbkjdkjrk/256_randomWorking.png (working -> color) https://www.software7.biz/iertzzlmbkjdkjrk/256_brokenStripes.png (broken -> grayscale) https://www.software7.biz/iertzzlmbkjdkjrk/256_semiRandomBroken.png (borken -> grayscale)

Summary

So it doesn't seem to be a bug in macOS, but during compilation/optimization of the assets into the Asset.car file. It seems to happen when the number of R,G,B values equal to 0xff is the same. There may be other cases.

A simple workaround seems to be to simply change the value of one pixel very slightly. This cannot be seen by the human eye.

like image 103
Stephan Schlecht Avatar answered Jan 02 '23 12:01

Stephan Schlecht