2

In order to upload an image file to my server, I need to get it's NSData. I am having trouble doing this right now, because my UIImage contains a CGImage.

Let me show you how I am doing things. When a user takes a photo, this is what I do with the captured photo:

NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];


UIImage *image = [[UIImage alloc]initWithData:imageData];


   _subLayer = [CALayer layer];


      image = [self selfieCorrection:image];


      image = [self rotate:image andOrientation:image.imageOrientation];


          CGRect cropRectFinal = CGRectMake(cropRect.origin.x, 140, cropRect.size.width, cropRect.size.height);

          CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRectFinal);


_subLayer.contents = (id)[UIImage imageWithCGImage:imageRef].CGImage;

In the above code, I create a UIImage, and initialize it with the imageData object. I also create a layer object called _subLayer that will display the final image on the screen. The image's orientation is then rotated and corrected, and then I setup a CGRect to crop the part of the image I want to keep.

The most important part are the last 2 statements. I create a CGImageRef called imageRef using the original UIImage. Then, in the last statement, I set the contents property of _subLayer to equal my final image.

A little further down in this same view controller, inside of an IBAction I have the following statement which helps me pass the image to my next view controller: sendFriendsVC.finalPhotoToSend = _subLayer.contents;

finalPhotoToSend is a property that I have setup in the header file of my next view controller like this:

@property (nonatomic, retain) UIImage *finalPhotoToSend;

The data is successfully passed when I segue to the next view controller, but when I NSLog finalPhotoToSend, even though it is a UIImage, it prints as this to the console:

<CGImage 0x1563dac0>

In order to upload photos to my backend server service, it requires me to create an object using NSData. I have tried using these 2 methods to get the NSData out of the finalPhotoToSend object:

NSData *imageData = UIImageJPEGRepresentation(finalPhotoToSend, 0.7);

and

NSData *imageData = UIImagePNGRepresentation(finalPhotoToSend);

But those always give me the following error in xcode:

NSInvalidArgumentException', reason: '-[__NSCFType CGImage]: unrecognized selector sent to instance

I am not sure what to do. Is there a different method I should be using to get NSData out of my UIImage since it is technically holding a CGImage? Should I be doing something differently before I even pass the data to my next view controller?

Edit for Michael:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:self {


    if ([segue.identifier isEqualToString:@"mediaCaptureToSendToFriendsSegue"]) {


    SendToFriendsViewController *sendFriendsVC = segue.destinationViewController;


        sendFriendsVC.finalPhotoToSend = _subLayer.contents;


    }
}
user3344977
  • 3,584
  • 4
  • 32
  • 88

2 Answers2

3

I just figured it out. Here's what I ended up using for the IBAction method implementation:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:self {


    if ([segue.identifier isEqualToString:@"mediaCaptureToSendToFriendsSegue"]) {


        SendToFriendsViewController *sendFriendsVC = segue.destinationViewController;


        UIImage* image2 = [UIImage imageWithCGImage:(__bridge CGImageRef)(_subLayer.contents)];

        sendFriendsVC.finalPhotoToSend = image2;


    }
}

I'm new to objective-c and not really entirely sure what the following statement is even doing:

UIImage* image2 = [UIImage imageWithCGImage:(__bridge CGImageRef)(_subLayer.contents)];

But xcode suggested it and it works. Now on the next view controller, the finalPhotoToSend object NSLogs as a UIImage instead of a CGImage.

user3344977
  • 3,584
  • 4
  • 32
  • 88
2

Better answer:

You need to truly set a UIImage object (and not a CGImage pointer) to a property that you've declared to be a UIImage object.

Original:

if "finalPhotoToSend" is a property, you should be doing:

NSData *imageData = UIImageJPEGRepresentation(self.finalPhotoToSend, 0.7);

and not:

NSData *imageData = UIImageJPEGRepresentation(finalPhotoToSend, 0.7);
Michael Dautermann
  • 88,797
  • 17
  • 166
  • 215
  • that was a typo. I am using it as a global variable: _finalPhotoTosend. Either way, that's not the problem. I need to figure out a solution in regards to getting the NSData from the object. – user3344977 Mar 02 '14 at 23:24
  • can you edit your question to show you how set the "`finalPhotoToSend`" property? – Michael Dautermann Mar 02 '14 at 23:26
  • just to be sure, I did include the statement: sendFriendsVC.finalPhotoToSend = _subLayer.contents; But I will edit the question and add the full IBAction that contains this statement. – user3344977 Mar 02 '14 at 23:29
  • Oh yeah, there I see it. So when you do "`_subLayer.contents = (id)[UIImage imageWithCGImage:imageRef].CGImage`", you're setting "`.contents`" to a CGImage and not a UIImage. And you can't do "`UIImageJPEGRepresentation`" off a CGImage. No wonder you're getting that exception. – Michael Dautermann Mar 02 '14 at 23:30
  • I understand, but then why am I able to store this CGImage in the UIImage object finalPhotoToSend? Even though I'm storing it in a UIImage, is it technically still a CGImage? – user3344977 Mar 02 '14 at 23:33
  • Because you're just setting an address of an object and not yet calling a method on that object. You attempt to do something with that object when you call "`UIImageJPEGRepresentation`", which is why it's bombing out with an exception. Why not set that property to a true UIImage object and not a CGImage (which is a CFType and not even an Objective-C object)? Then your problem should magically disappear. – Michael Dautermann Mar 02 '14 at 23:42
  • Yep exactly. I still have a lot of learning to do with objective-c, but appreciate your patience and help Michael. Thanks again. – user3344977 Mar 02 '14 at 23:47
  • I am really glad you got it solved (and summarized it nicely in your own follow-up answer). – Michael Dautermann Mar 02 '14 at 23:54