resizableImageWithCapInsets bug with fractional pixels

Originator:igeek1
Number:rdar://15959788 Date Originated:31-Jan-2014 03:53 PM
Status:Open Resolved:
Product:iOS Product Version:iOS 7 SDK
Classification:Serious Bug Reproducible:Always
 
Summary:
This is an iOS 6-only bug, and it is fixed in iOS 7, but I wanted to file it in case this specific case was not known, and people were looking for workarounds. We encountered this bug while working on an app that supports 5.1, 6, and 7.

When creating a resizableImageWithCapInsets from an image that is less than 1pt wide, weird things happen on iOS 6, and different weird things happen on iOS 5, but not on iOS 7.

Steps to Reproduce:
(see attached sample code)
1. Use Quartz drawing to generate a small image, suitable for stretching. I want a UINavigationBar with a 1px stroke on the bottom, so I am making a 1px wide by 2px tall image. I want a true 1px stroke on Retina devices, so I have a function, screenPixel(), which returns 1 on non-Retina displays and 0.5 on Retina displays. In the sample code, the image consists of a red pixel on top of a blue pixel.
2. Make a new image from that image using resizableImageWithCapInsets: and use a cap inset with screenPixel() on the bottom and 0 on the other sides.
3. Use the image as the background image for a UINavigationBar.

Expected Results:
The bottom pixel is within the insets, so the top pixel stretches to fill the remaining space. In the sample code, we get a red bar with a 1px blue stroke on the bottom.

Actual Results:
The 1 ✕ 2 px resizable image works fine on iOS 7, but on iOS 5 and 6, it seems to introduce a third, middle pixel, which appears to be the average of the top and bottom pixels. The nav bar ends up purple, with a 1px red stroke at the top, and a 1px blue stroke at the bottom.

In the sample code, we have included our workaround, which is to make a 1 ✕ 3 px image with the top two pixels the same color that we want for the nav bar.

Version:
Xcode 5.0.2 (5A3005)
iOS 7 SDK

Notes:
Including two versions of the sample project: one for the iOS 7 SDK with a 6.1 deployment target, and one for building and running with the iOS 5.1 SDK/runtime.

Configuration:
We see this bug in the following conditions:
Retina displays only (because our screenPixel() function returns whole numbers on non-Retina displays).
Built with iOS 7 SDK, running under iOS 6.
Built with iOS 5.1 SDK, running under iOS 5 SDK (except the effect is slightly different: instead of purple, we get a blurry gradient effect - see screenshot.)

We do not see this bug when building in the iOS 7 SDK and running on iOS 7.

Attachments:
Sample code and screenshots: http://cl.ly/TfHz

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!