5

I am getting EXEC_BAD_ACCESS errors in a CGContextDrawImage call and trying to trace it back. I have a PNG image and running a UIImagePNGRepresentation o it gives me NSData instance.

I need to convert this to CGImageRef instance, so I can run the CGImageCreateWithPNGDataProvider method with this CGImageRef.

I tried two ways: 1) To cast it.

CGImageRef ref = (CGDataProvider)nsdata;

2) To run CGDataProviderCreateWithCFData(nsdata);

First case returns empty image, though command doesnt fail. The reason I tried the second case, even though I have NSData and not CFData is because I remember reading it accepts both. Whatever be the reason, it is failing due to this.

Is there a way I can use my PNG NSData to create a CGImage that is not corrupted? Please help.

THanks

GAS
  • 51
  • 1
  • 2

2 Answers2

9

Your second try is almost right. CFData and NSData are “toll-free bridged”. Anything that accepts a CFDataRef also accepts NSData (and vice-versa) — you just have to cast correctly.

You need:

CGDataProviderCreateWithCFData((CFDataRef)myNSData);
Todd Yandell
  • 14,656
  • 2
  • 50
  • 37
  • 2
    If you have ARC, Use __bridge to convert directly: CGDataProviderCreateWithCFData((__bridge CFDataRef)myNSData); – situee Nov 08 '12 at 02:50
3

The first is very wrong. You can not turn an NSData instance into a CGImageRef simply by casting it.

The second should work fine. You will have to cast the NSData instance to a CFDataRef but that is perfectly legal due to what Apple calls toll-free bridging.

Here is another and much easier method:

NSData* data = ... get raw image data from somewhere (PNG, JPEG, etc.) ...;
UIImage* image = [UIImage imageWithData: data];
CGImageRef imageRef = image.CGImage;

I prefer to use the higher level UIImage methods to load images and then use image.CGImage for lower level Core Graphics functions. Don't forget to properly retain the UIImage if you need to keep it around.

Stefan Arentz
  • 34,311
  • 8
  • 67
  • 88
  • `image.CGImage` is definitely better than `(CGImageRef)[(id)CGImageCreateWithPNGDataProvider((CGDataProviderRef)[(id)CGDataProviderCreateWithNSData((CFDataRef)UIImagePNGRepresentation(image)) autorelease],0,0,0) autorelease]` – tc. Aug 21 '10 at 02:26
  • 1
    Note that UIKit is not thread-safe, so creating `UIImage` instances on background threads can lead to problems. In some cases it's better to directly create a `CGImageRef`. – Jonas Sourlier May 15 '13 at 18:46
  • 1
    @cheeesus, according to Apple's documentation (https://developer.apple.com/reference/uikit/uiimage), it is safe to create UIImage instances in background threads: *"The immutable nature of image objects also means that they are safe to create and use from any thread."* – Arda Mar 21 '17 at 06:38