Bug 37713 - CGImage.DrawImage does not render many PNG images
Summary: CGImage.DrawImage does not render many PNG images
Status: RESOLVED DUPLICATE of bug 34633
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll ()
Version: XI 9.2
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Rolf Bjarne Kvinge [MSFT]
Depends on:
Reported: 2016-01-15 04:08 UTC by bobme981
Modified: 2016-01-29 10:50 UTC (History)
2 users (show)

Is this bug a regression?: ---
Last known good build:

fixed test case (1.09 MB, application/zip)
2016-01-28 19:09 UTC, Rolf Bjarne Kvinge [MSFT]

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description bobme981 2016-01-15 04:08:07 UTC
Separating this issue out from bug #37536. Originally we suspected that the two were related, but it appears they are not, since the workaround only fixes the crash, not the rendering issue. The actual fix has not been released, though, so we are only assuming that it addresses only the crash as well.

You can repro this bug using the repro solution attached to #37536.
Comment 1 bobme981 2016-01-28 17:20:58 UTC
Copying the description here for reference:

The repro app displays a custom animation control. The control loops through 70 different pre-loaded CGImages (one every 20 ms) and draws them using CGContext.DrawImage.

PROBLEM: Around 80% of the images are not rendered on the screen at all, even though the DrawImage call succeeds. This occurs ONLY when the app is run on an actual iPad, and not in the iOS simulator.

This is serious issue affecting one of the major visuals in a consumer product. If someone could take a look at this long enough to at least suggest a workaround that would be extremely helpful.
Comment 2 bobme981 2016-01-28 17:30:15 UTC
More info:
- The same specific images fail to render every time.
- All of the images render correctly in the iOS simulator, in an Android emulator, on an Android device, and in a number of different image viewers/editors on both Windows and Mac.
- We opened and re-saved the images using an image tool, which resulted in somewhat different file sizes, but it did not resolve the issue.
Comment 3 Rolf Bjarne Kvinge [MSFT] 2016-01-28 17:43:40 UTC
If I apply the fix here: https://gist.github.com/rolfbjarne/1452c400fbbbe7da071f the earth seems to spin fine on device for me (same as it does on the simulator) - but there is a hiccup when it loops (I assume that's expected?)

Is anything printed to the iOS Device log (in Xamarin Studio's View -> Pads -> iOS Device Log) and/or the Application Output when running on device?

Also which device(s) have you tried on (and which iOS versions do those devices have)?
Comment 4 bobme981 2016-01-28 18:43:30 UTC
Yes, the hiccup is actually expected. While investigating the issue we reordered some of the images, then inadvertently left them that way. When they are in the right order there's no hiccup. :)

Nothing is showing up for us in either the iOS Device log or in Application Output when the issue occurs.

Device notes from the original bug:
Simulator: iPad 2, iOS 9.2
Device: iPad 4, iOS 9.2
Comment 5 bobme981 2016-01-28 18:47:05 UTC
Some specific image #'s that do/don't render:
BAD: 2-6, most of the range 0-40
GOOD: 45-68
Comment 6 bobme981 2016-01-28 19:03:26 UTC
Confirmed repro on a second iPad 4, both running iOS 9.2.1. One has 16 GB, the other 32 GB storage. Otherwise identical.
Comment 7 Rolf Bjarne Kvinge [MSFT] 2016-01-28 19:09:58 UTC
Created attachment 14771 [details]
fixed test case

I'm attaching the code I'm running, can you try this code so that we can make sure we're running the exact same code?
Comment 8 bobme981 2016-01-28 20:57:37 UTC
Your code won't build for us. We have Xamarin.iOS, which has no CGDataProvider(byte[] buffer) overload (although it would be nice if it did). The original code calls CGDataProvider(byte[], int, int).
Comment 9 bobme981 2016-01-28 21:16:48 UTC
It looks like you made some other changes too, including some project settings. If we revert the constructor call mentioned above, the code builds, but will not deploy: 

Installing application bundle
error MT1006: Could not install the application '/.../HelloWorld.iOS.app' on the device Demo32: AMDeviceSecureInstallApplicationBundle returned: 0xe8000087 (kAMDIncorrectArchitectureError).
Comment 10 Rolf Bjarne Kvinge [MSFT] 2016-01-29 10:44:18 UTC
So I can reproduce your problem now (I couldn't earlier because I was using a newer version of Xamarin.iOS with an additional fix for CGDataProvider).

The bug is that the image data is freed when the GC collects CGDataProvider, and if the CGImage tries to fetch the image data after that, you'll get random behavior (or even crashes).

There are at least two workarounds:

* Make sure the CGDataProvider is not freed by the GC. One simple way of doing this is to add them to a static list (https://gist.github.com/rolfbjarne/2d5c19ef879387ee1b6f), but this might be a problem if you have many images (it uses memory).
* Another option is to store the image data in a file and use the CGDataProvider's constructor that takes a filename.

*** This bug has been marked as a duplicate of bug 34633 ***
Comment 11 Rolf Bjarne Kvinge [MSFT] 2016-01-29 10:50:41 UTC
You can also update to the latest service release (from yesterday), where this issue is fixed and your code works just fine.