Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Mockup & CodeGen, iPhone & iPad
($9.99)

Make your own iPhone apps
and run them live!
(free)

Manu
($0.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum

View Single Post
Old 06-07-2009, 11:18 AM   #1 (permalink)
NewiPhoneDeveloper
Registered Member
 
Join Date: Jul 2008
Posts: 459
Default Merging content of UIImageView and EAGLview

Hello,

I'm almost done with my current project, but somehow can't solve the following problem.

My app uses parts of the GLPaint demo app, to allow the user to draw on the iPhone screen. The EAGLview is set to transparent, using

Code:
eaglLayer.opaque = NO;
Below I have a UIImageView, which holds an image. This all looks great, but I haven't been able to merge both into one image, that can be saved to the photo library.

Here is what I tried so far:

1) Trying to make a simple screenshot

Code:
UIGraphicsBeginImageContext(self.window.bounds.size);
[self.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
	
UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);
This doesn't work, as it will only grab contents of the UIImageView, which is below my EAGLview.

2) Grabbing content of the EAGLview and putting it in a new UIImageView, which is positioned above the old UIImageView:

Code:
- (CGImageRef) glToUIImage {
    NSInteger myDataLength = 320 * 480 * 4;
	
    // allocate array and read pixels into it.
    GLubyte *buffer = (GLubyte *) malloc(myDataLength);
    glReadPixels(0, 0, 320, 480, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
	
    // gl renders "upside down" so swap top to bottom into new array.
    // there's gotta be a better way, but this works.
    GLubyte *buffer2 = (GLubyte *) malloc(myDataLength);
    for(int y = 0; y <480; y++)
    {
        for(int x = 0; x <320 * 4; x++)
        {
            buffer2[(479 - y) * 320 * 4 + x] = buffer[y * 4 * 320 + x];
        }
    }
	
    // make data provider with data.
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL);
	
    // prep the ingredients
    int bitsPerComponent = 8;
    int bitsPerPixel = 32;
    int bytesPerRow = 4 * 320;
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
	
    // make the cgimage
    CGImageRef imageRef = CGImageCreate(320, 480, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
	
    // then make the uiimage from that
    UIImage *myImage = [UIImage imageWithCGImage:imageRef];
    return myImage;
}
This returns content of the EAGLview in a UIImage. Works fine, except for one major problem: There is no transparency. So, parts that are transparent are black.

3) Grabbing content of EAGLview (like before) and merging it with content of my UIImageView, using quartz.
Code:
        CGImageRef		brushImage;
	CGContextRef	brushContext;
	GLubyte			*brushData;
	size_t			width, height;
	
	brushImage =  [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"imageOfUIImageView" ofType:@"png"]].CGImage;
	
	void *          bitmapData;
    int             bitmapByteCount;
    int             bitmapBytesPerRow;
	CGColorSpaceRef colorSpace;
	bitmapData = malloc(bitmapByteCount);
	
	bitmapBytesPerRow   = (320 * 4);// 1
    bitmapByteCount     = (bitmapBytesPerRow * 480);
	colorSpace = CGImageGetColorSpace(image);
	
	
	
	width = CGImageGetWidth(brushImage);
	height = CGImageGetHeight(brushImage);
	brushData = (GLubyte *) malloc(320 * 480 * 4);
	// Use  the bitmatp creation function provided by the Core Graphics framework. 
	
	brushContext = CGBitmapContextCreate (bitmapData,
										  320,
										  480,
										  8,      
										  bitmapBytesPerRow,
										  colorSpace,
										  kCGImageAlphaPremultipliedFirst);
	
    
	// After you create the context, you can draw the  image to the context.
        // image is a UIImage, that holds the image, returned from the glToUIImage method above
        // Draw the EAGLview content (now in image) to the context
	CGContextDrawImage(brushContext, CGRectMake(0.0, 0.0, (CGFloat)320, (CGFloat)480), image.CGImage);
	
	//Set the blend mode
	CGContextSetBlendMode (brushContext, kCGBlendModeLighten); //lighten seems to give the "best" result
        //draw the background to the context
	CGContextDrawImage(brushContext, CGRectMake(0.0, 0.0, (CGFloat)320, (CGFloat)480), brushImage);
	
	//create a new image, that combines both EAGLview and my background image
	CGImageRef mergedImage = CGBitmapContextCreateImage(brushContext);	
	CGContextRelease(brushContext);
	//write it to photolibrary
	UIImageWriteToSavedPhotosAlbum([UIImage imageWithCGImage:image], self, nil, nil);
This doesn't work either. Depending on the blend mode I choose, the result looks sometimes better, sometimes worse, but is never close to what I need. On the other hand, if I simply push the home and on/off button to make a screenshot manually, the result is exactly what I need.

Maybe you have some ideas, how this can be achieved. It's really the final touch for my app and I definitely don't want the user to make the screenshot manually.

Any help appreciated! Thanks in advance.
NewiPhoneDeveloper is offline   Reply With Quote
 

» Advertisements
» Stats
Members: 158,836
Threads: 89,209
Posts: 380,642
Top Poster: BrianSlick (7,129)
Welcome to our newest member, abbylowin
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 03:28 AM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.