Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

RossOliver

macrumors regular
Original poster
Nov 6, 2006
157
0
Hey,

I'm having problems with a CGImage. I have overridden a UIView allowing me to initialize it with an 'underlay' image that originally fills the view. I can then set the overlayImage instance variable to a CGImage and it is draw on top of the 'underlay' image using the drawRect method:

Code:
ItemView.m

-( id )initWithItemUnderlay:( UIImage * )itemUnderlay frame:( CGRect )frame
{
    if( self = [super initWithFrame:frame] )
	{
		UIImageView *imageView = [[UIImageView alloc] initWithImage: itemUnderlay];
		[self addSubview:imageView];
		[imageView release];
		overlayImage = NO;
    }
    return self;
}

-( void )setOverlayImage:( CGImageRef )newOverlayImage
{
	overlayImage = newOverlayImage;
}

-( CGImageRef )overlayImage
{
	return overlayImage;
}

-( void )drawRect:( CGRect )rect
{
	if( overlayImage )
	{
		CGContextRef context = UIGraphicsGetCurrentContext(); 
		CGContextDrawImage( context, rect, overlayImage );
	}
}

This view is created with an underlay/overlay image in a different class:

Code:
itemView = [[ItemView alloc] initWithItemUnderlay:defaultItemUnderlay 
		frame:CGRectMake( ITEM_VIEW_X, ITEM_VIEW_Y, ITEM_VIEW_WIDTH, ITEM_VIEW_HEIGHT )];
[itemView setOverlayImage:[UIImage imageNamed:@"MyImage.png"].CGImage];
[customTableView addSubview:itemView];

So far this works fine - the underlay image is set and the overlay image is draw on top of it. I can then change the overlayImage using setOverlayImage and it redraws the overlay image as I would want.

However, the simulator crashes if I use an image I gather from the web. I have an Item class that can hold a CGImageRef. An instance of the Item class is created and the image is set to an image gathered from the web:

Code:
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
[item setImage:[UIImage imageWithData:imageData].CGImage];

This item class gets returned to the class that originally set the overlay/underlay images. I know the image gathered is correct as I have displayed it as a UIImage before. However, if I now set the CGImage from the Item class as the overlay image the simulator crashes:

Code:
[itemView setOverlayImage:[item image]]; // doesn't work
// [itemView setOverlayImage:[UIImage imageNamed:@"MyImage.png"].CGImage] // does work.
[itemView setNeedsDisplay];

Is there something special required to retain a CGImage in an instance variable? I've been pulling my hair out over this for days - if anyone can help I would really appreciate it...

In case it helps, this is a chunk of the report from the crash:

Code:
Process:         MyApp [14803]
Path:            /Users/Ross/Library/Application Support/iPhone Simulator/User/Applications/583EAA3F-4E73-4D8C-8928-ACCC6837C773/MyApp.app/MyApp
Identifier:      MyApp
Version:         ??? (???)
Code Type:       X86 (Native)
Parent Process:  launchd [89]

Date/Time:       2008-04-28 02:05:18.256 +0100
OS Version:      Mac OS X 10.5.2 (9C7010)
Report Version:  6

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000044b2e002
Crashed Thread:  0

Thread 0 Crashed:
0   com.apple.CoreGraphics        	0x31062bd6 decode_byte_8bpc_3 + 70
1   com.apple.CoreGraphics        	0x30fcb27e decode_data + 4614
2   com.apple.CoreGraphics        	0x30fc9f54 img_decode_read + 1641
3   com.apple.CoreGraphics        	0x3102fad5 img_interpolate_read + 656
4   com.apple.CoreGraphics        	0x30fc7351 img_data_lock + 4996
5   com.apple.CoreGraphics        	0x30fc55ef CGSImageDataLock + 168
6   libRIP.A.dylib                	0x00289160 ripc_AcquireImage + 3116
7   libRIP.A.dylib                	0x002784a0 ripc_DrawImage + 3652
8   com.apple.CoreGraphics        	0x30fc53d5 CGContextDrawImage + 397
9   MyApp                        	0x000060f7 -[ItemView drawRect:] + 73 (ItemView.m:42)
10  UIKit                         	0x30b4a820 -[UIView(CALayerDelegate) drawLayer:inContext:] + 452
11  QuartzCore                    	0x32022512 -[CALayer drawInContext:] + 65
12  QuartzCore                    	0x320224b9 backing_callback + 69
13  QuartzCore                    	0x320220cd CABackingStoreUpdate + 1938
14  QuartzCore                    	0x3202176e -[CALayer _display] + 896
15  QuartzCore                    	0x32015c32 CALayerDisplayIfNeeded + 178
16  QuartzCore                    	0x32013f77 CAContextCommitTransaction + 191
17  QuartzCore                    	0x32013c66 CATransactionCommit + 205
18  com.apple.CoreFoundation      	0x967e29c2 __CFRunLoopDoObservers + 466
19  com.apple.CoreFoundation      	0x967e3c60 CFRunLoopRunSpecific + 656
20  com.apple.CoreFoundation      	0x967e4d18 CFRunLoopRunInMode + 88
21  GraphicsServices              	0x31670e4a GSEventRunModal + 217
22  GraphicsServices              	0x31670f0f GSEventRun + 115
23  UIKit                         	0x30b2679b -[UIApplication _run] + 441
24  UIKit                         	0x30b30de0 UIApplicationMain + 1224
25  MyApp                        	0x00001ee4 main + 102 (main.m:14)
26  MyApp                        	0x00001e52 start + 54

Thanks for your time.
 

RossOliver

macrumors regular
Original poster
Nov 6, 2006
157
0
I've narrowed the problem down to these few lines:

Code:
NSURL *imageURL = [NSURL URLWithString:[[query objectAtIndex:0] stringValue]];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
//[item setImage:[UIImage imageWithData:imageData].CGImage];
[item setImage:[UIImage imageNamed:@"test.jpg"].CGImage];

By replacing the commented out line with the line using an image in my application it works perfectly. Is there a step I have missed out when converting the imageData to a CGImage?

As I said in my other post, the image itself works correctly when I just make it into a UIImage from the NSURL instead of CGImage...

Another odd thing I noticed was that the image is flipped upside down before it's drawn in drawRect :confused:

-Ross

[edit]

Managed to get the image the correct way up using this useful code snippet:

Code:
	CGContextTranslateCTM( context, 0, CGRectGetMaxY( rect ) );
	CGContextScaleCTM( context, 1.0, -1.0 );
	rect = CGRectOffset( rect, 0, -rect.origin.y );
 

ecume

macrumors newbie
Sep 16, 2003
9
0
did you find a fix?

I'm also running into random crashes when doing exactly your senario - compositing two images, one of which was grabbed from the web. It looks like the issue is in UIGraphicsGetCurrentContext();

I f I just use local UIImages = no problems...
 

yoavhacohen

macrumors newbie
Jan 31, 2008
8
0
Try to call it from the main thread:

[self.imageViewer performSelectorOnMainThread:mad:selector(setImage:) withObject:(id)cgImage waitUntilDone:NO];
 

idelovski

macrumors regular
Sep 11, 2008
235
0
In the code above (1st post) you never retain it. I suppose it all works nice with -imageNamed: because those images tend to stick around for a long time.
 

idelovski

macrumors regular
Sep 11, 2008
235
0
Ups, you are right. I wasn't paying attention to all the dates. The guy in front of me had a fresh time on his post and I probably assumed all was fine.

Now when I looked at this thread more carefully I have noticed that original message from 2008 resurfaced twice so far. First time after 8 months and now after more than two years. Second interesting thing is the label on yoavhacohen:

Joined in 2008, macrumors newbie.
 

ArtOfWarfare

macrumors G3
Nov 26, 2007
9,558
6,058
Second interesting thing is the label on yoavhacohen:

Joined in 2008, macrumors newbie.

Member titles are mostly based on the number of posts a member has made. They probably just haven't posted much since joining the forums.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.