Using a UIImage* in oF

Hello,

I am using an Obj-C image picker to select a picture that I then want to use with oF code. The way I tried doing it is by creating an ofTexture, allocating it to 320x480 GL_RGBA and passing that to the

  
void iPhoneLoadImageFromUIImage(UIImage *image, GLuint *spriteTexture);  

function. The first parameter is just the UIImage I’m getting from my image picker controller/view/whatever class.

This is unfortunately not working.
If I just wait for the image picker to finish then grab the UIImage, the application crashes at line 54 “cgImage = uiImage.CGImage;” of ofxiPhoneUtils.mm.
If I assign this selected UIImage as the image in a UIImageView that is part of my image picker controller/view object, then the app does not crash, but the ofTexture gets filled with white pixels.

Here’s some of my code:

ImagePickerController.h

  
  
#import <UIKit/UIKit.h>  
#import "ofMain.h"  
  
@interface ImagePickerController : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate> {  
	IBOutlet UIButton *cameraButton;  
    IBOutlet UIButton *albumButton;  
    IBOutlet UIImageView *imageView;  
      
    BOOL done;  
    UIImage* image;  
}  
  
@property (nonatomic, retain) UIImage* image;  
  
- (IBAction)openCameraPicker;  
- (IBAction)openAlbumPicker;  
- (bool)isDone;  
  
@end  
  

ImagePickerController.mm

  
  
#import "ImagePickerController.h"  
  
@implementation ImagePickerController  
  
@synthesize image;  
  
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {  
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {  
        done = NO;  
    }  
    return self;  
}  
  
- (void)viewDidLoad {  
    if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {  
        // disable the camera button  
        [cameraButton setEnabled:NO];  
        [cameraButton setAlpha:0.5];  
    }  
    [super viewDidLoad];  
}  
  
- (IBAction)openCameraPicker {  
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {  
        UIImagePickerController *picker;  
        picker = [[UIImagePickerController alloc] init];  
        picker.sourceType = UIImagePickerControllerSourceTypeCamera;  
          
        picker.allowsImageEditing = YES;  
        picker.delegate = self;  
        [self presentModalViewController:picker animated:YES];  
    }  
}  
  
- (IBAction)openAlbumPicker {  
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {  
        UIImagePickerController *picker;  
        picker = [[UIImagePickerController alloc] init];  
        picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;  
          
        picker.allowsImageEditing = YES;  
        picker.delegate = self;  
        [self presentModalViewController:picker animated:YES];  
    }  
}  
  
- (void)imagePickerController:(UIImagePickerController*)picker   
        didFinishPickingImage:(UIImage*)img  
                  editingInfo:(NSDictionary*)editingInfo {  
    [self setImage:img];  
    [[picker parentViewController] dismissModalViewControllerAnimated:YES];  
}  
  
- (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker {  
    [[picker parentViewController] dismissModalViewControllerAnimated:YES];  
}  
  
- (void)setImage:(UIImage*)img {  
    image = img;  
    imageView.image = image;  // IF I COMMENT THIS OUT, THE APP CRASHES  
    done = YES;  
}  
  
- (bool)isDone {  
    return (done == YES);  
}  
  
  
@end  
  

testApp.mm

  
  
#include "testApp.h"  
  
//--------------------------------------------------------------  
void testApp::setup(){	  
    ofBackground(0, 0, 0); // set background to black  
    ofSetBackgroundAuto(true); // set background to clear automatically every frame  
    ofSetFrameRate(60); // set desired framerate to 60fps  
      
    // initialize the accelerometer and multitouch:  
    ofxAccelerometer.setup();  
    ofxMultiTouch.addListener(this);  
      
    state = STATE_PICK_IMAGE;  
      
    imagePickerController = [[ImagePickerController alloc] initWithNibName:@"ImagePickerView" bundle:nil];  
    [[[UIApplication sharedApplication] keyWindow] addSubview:imagePickerController.view];  
  
}  
  
  
//--------------------------------------------------------------  
void testApp::update() {  
    if (state == STATE_PICK_IMAGE && [imagePickerController isDone]) {  
        printf("PICK IMAGE DONE!\n");  
        state = STATE_LEFT_EYE;  
        printf("siiize %f x %f\n", imagePickerController.image.size.width, imagePickerController.image.size.height);  
        texIn.allocate(imagePickerController.image.size.width, imagePickerController.image.size.height, GL_RGBA);  
        iPhoneLoadImageFromUIImage([imagePickerController image], &texIn.texData.textureName[0]);  
        [[imagePickerController view] setAlpha:0];  
    }  
    //	printf("update()\n");  
}  
  
//--------------------------------------------------------------  
void testApp::draw() {  
    if (state == STATE_LEFT_EYE) {  
        //printf("draw\n");  
        texIn.draw(0, 0);  
    }  
}  
  

Any ideas?

Thanks,
-Elie

Hey, that’s a very valid thing to want to do and should be in ofxiPhone, so i just added it. If you get the latest ofxiPhone from svn http://code.google.com/p/ofxiphone/ and include ofxiPhone.h, you can call iPhoneUIImageToOFImage(UIImage *uiImage, ofImage &outImage); So pass it a pointer to your UIImage, and also an empty ofImage. upon return your ofImage will have the dimensions and pixels of your UIImage.

I haven’t actually tested it, so lemme know if it works :stuck_out_tongue: (I have a feeling it might end up upside down).

P.S. the function you were using: iPhoneLoadImageFromUIImage, creates a raw opengl texture out of the UIImage, not an ofTexture. so that’s why it wasn’t working for you.

P.S. i renamed the functions iPhoneLoadImageFromBundle and iPhoneLoadImageFromUIImage to iPhoneBundleImageToGLTexture and iPhoneUIImageToGLTexture cos they were a bit misleading before. Hope that doesn’t cause too many problems.

Hey memo,

Awesome, thanks a lot! Just tested it and it works, but as you say, the image is upside down :slight_smile:

I figured out a way to do it with an ofTexture that’s sort of similar, could be useful to have an iPhoneUIImageToOFTexture function…

  
  
        CGImageRef imageRef = [[imagePickerController image] CGImage];  
        NSUInteger width = CGImageGetWidth(imageRef);  
        NSUInteger height = CGImageGetHeight(imageRef);  
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();  
        unsigned char* rawData = (unsigned char*)malloc(height * width * 4);  
        NSUInteger bytesPerPixel = 4;  
        NSUInteger bytesPerRow = bytesPerPixel * width;  
        NSUInteger bitsPerComponent = 8;  
        CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);  
        CGColorSpaceRelease(colorSpace);  
          
        CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);  
        CGContextRelease(context);  
          
        texIn.allocate(width, height, GL_RGBA);  
        texIn.loadData(rawData, width, height, GL_RGBA);  
        texIn.texData.bFlipTexture = false;  // TODO add this to ofTexture.loadData(...)  
  

I also needed to flip the texture in this one. Does it make sense that ofTexture.loadData(…) has the following code? Shouldn’t it also be false?

  
  
	#ifdef TARGET_OF_IPHONE  
		texData.bFlipTexture = true; // textures need to be flipped for the iphone  
	#else  
		texData.bFlipTexture = false;  
	#endif  
  

maybe a little late, it seems like you’ve done most of this,

but i’ve had an imagepicker wrapper up for a bit on my site that I’ve been meaning to put into the ofxiphone distro

http://www.stfj.net/art/2009/ofxiPhone

it works for pulling images from the library, as well as the camera, and puts the images right into ofImages

memo just recently fixed the image flipping issue as well

zach

Nice one Zach, that’s exactly what I needed to do, it’s a great example of how to link Obj-C and C++ classes.

I did find one (sorta) bug: You create a new “bpp” variable in the loadPixels() method, so if you try to access the global “bpp” externally, it returns 0 as it is never initialized. Same thing with “glType”…

Actually, I just noticed something odd when using Zach’s image picker controller. It works as expected in the simulator, but when I test on the iPhone, if I use the camera as an input source, the resulting image is rotated 90 degrees. That doesn’t happen if I use the album as an input source.

Have you encountered this when using it?

Thanks,

huh that is pretty weird.
It’s possible that this is happening because I wrote it for an app that was showing in landscape mode… ill look at it and try and make the proper changes…

I’m assuming your app is in portrait mode?
If so, did you try removing the line about being in landscape mode from your plist file?

hmm didn’t think of that. i just checked though and the app was in portrait mode, so that’s not it…

very weird. maybe it was introduced when memo updated the drawing code… last i used it it worked okay… ill look at it tomorrow

Hey,

I just finally got back to this. I can’t really figure out why the image is rotated…
Same deal, it only rotates it 90 degrees if the source is the camera, and if I call ImagePicker.getOrientation() the result is always OFX_IMG_PICKER_UP.

Any ideas?

Thanks,
-Elie