How to add a CGImageRef to a NSDictionary? - nsdictionary

I have a CGImageRef variable and a CGRect (so no pointers) and I need to add it to an NSDictionary. Like an NSArray, NSDictionary-s only accept pointers. How can you add an CGImageRef or an CGRect anyway?

CGImageRef is already a pointer, but it's not (AFAIK) a pointer to a valid Cocoa object. You can turn a CGImage into a Cocoa NSBitmapImageRep with [[NSBitmapImageRep alloc] initWithCGImage:someimageref]. And NSValue is there to wrap primitive types like CGRect.

Related

EAGLContext to UIImage

In objective-C, I was able to render the EAGLContext to UIImage using glReadPixels to read the pixel data from the framebuffer, creating a CGImage using the pixel data, and then retrieving a UIImage from the context.
I am trying a new method in Swift, but it is returning an empty image. I would like to create a GLKView from the EAGLContext, and then use 'snapshot' to get the UIImage. The “myEaglContext” passed into the GLKView constructor has data on it.
let glkView = GLKView(frame: CGRect(x: 0,y: 0,width: self.frame.size.width,height: self.frame.size.height),context: myEaglContext)
glkView.bindDrawable()
glkView.display()
let image : UIImage = glkView.snapshot
Does anyone know why this approach is not working?

How to duplicate (copy) a CIImage

How can I duplicate a CIImage from another CIImage without going through rendering a CGImage
CIImage *copiedImage = [originalImage copy];
As you can read in the documentation, CIImage conforms to NSCopying.

Creating UIImage from CIImage

I am using some CoreImage filters to process an image. Applying the filter to my input image results in an output image called filterOutputImage of type CIImage.
I now wish to display that image, and tried doing:
self.modifiedPhoto = [UIImage imageWithCIImage:filterOutputImage];
self.photoImageView.image = self.modifiedPhoto;
The view however is blank - nothing is being displayed.
If I add logging statements that print out details about both filterOutputImage and self.modifiedPhoto, those logging statements are showing me that both those vars appear to contain legitimate image data: their size is being reported and the objects are not nil.
So after doing some Googling, I found a solution that requires going through a CGImage stage; vis:
CGImageRef outputImageRef = [context createCGImage:filterOutputImage fromRect:[filterOutputImage extent]];
self.modifiedPhoto = [UIImage imageWithCGImage:outputImageRef scale:self.originalPhoto.scale orientation:self.originalPhoto.imageOrientation];
self.photoImageView.image = self.modifiedPhoto;
CGImageRelease(outputImageRef);
This second approach works: I am getting the correct image displayed in the view.
Can someone please explain to me why my first attempt failed? What am I doing wrong with the imageWithCIImage method that is resulting in an image that seems to exist but can't be displayed? Is it always necessary to "pass through" a CGImage stage in order to generate a UIImage from a CIImage?
Hoping someone can clear up my confusion :)
H.
This should do it!
-(UIImage*)makeUIImageFromCIImage:(CIImage*)ciImage
{
self.cicontext = [CIContext contextWithOptions:nil];
// finally!
UIImage * returnImage;
CGImageRef processedCGImage = [self.cicontext createCGImage:ciImage
fromRect:[ciImage extent]];
returnImage = [UIImage imageWithCGImage:processedCGImage];
CGImageRelease(processedCGImage);
return returnImage;
}
I assume that self.photoImageView is a UIImageView? If so, ultimately, it is going to call -[UIImage CGImage] on the UIImage and then pass that CGImage as the contents property of a CALayer.
(See comments: my details were wrong)
Per the UIImage documentation for -[UIImage CGImage]:
If the UIImage object was initialized using a CIImage object, the
value of the property is NULL.
So the UIImageView calls -CGImage, but that results in NULL, so nothing is displayed.
I haven't tried this, but you could try making a custom UIView and then using UIImage's -draw... methods in -[UIView drawRect:] to draw the CIImage.

(iphone) am I creating a leak when creating a new image from an image?

I have following code as UIImage+Scale.h category.
-(UIImage*)scaleToSize:(CGSize)size
{
UIGraphicsBeginImageContext(size);
[self drawInRect:CGRectMake(0, 0, size.width, size.height)];
// is this scaledImage auto-released?
UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}
I use image obtained as above and use it as following.
UIImage* image = [[UIImage alloc] initWithData: myData];
image = [image scaleToSize: size]; <- wouldn't this code create a leak since
image(before scaling) is lost somewhere?
i guess above codes work fine if image was first created with auto-release.
But if image was created using 'alloc', it would create a leak in my short knowledge.
How should I change scaleToSize: to guard against it?
Thank you
EDIT -
I'd like to use alloc(or retain)/release on UIImage so that I can keep the # of UIImage in memory at a point small.
(i'm loading many UIImages in a loop and device can't take it)
Notice that your code could be rewritten as:
UIImage *image = [[UIImage alloc] initWithData:myData];
UIImage *scaledImage = [image scaleToSize:size];
image = scaledImage;
so let’s see what happens:
image is obtained via alloc, hence you own that object
scaledImage is obtained via a method that returns an autoreleased object since UIGraphicsGetImageFromCurrentImageContext() returns an autoreleased object
you own the original image but you don’t own scaledImage. You are responsible for releasing the original image, otherwise you have a leak.
In your code, you use a single variable to refer to both objects: the original image and the scaled image. This doesn’t change the fact that you own the first image, hence you need to release it to avoid leaks. Since you lose the original image reference by using the same variable, one common idiom is to send -autorelease to the original object:
UIImage *image = [[[UIImage alloc] initWithData:myData] autorelease];
image = [image scaleToSize:size];
Or, if you’d rather release the original image instead of autoreleasing it,
UIImage *image = [[UIImage alloc] initWithData:myData];
UIImage *scaledImage = [image scaleToSize:size];
[image release];
// use scaledImage from this point on, or assign image = scaledImage
IMO, it doesn’t make sense to change scaleToSize:. It is an instance method that creates an (autoreleased) image based on a given UIImage instance. It’s similar to -[NSString stringByAppendingString:], which creates a (an autoreleased) string based on a given NSString instance. It doesn’t and shouldn’t care about the ownership of the original string, and the same applies to your scaleToSize: method. How would the method know whether the caller wants to keep the original image?
I’d also rename scaleToSize: to imageByScalingToSize to make it similar to Cocoa’s naming convention — you’re getting an image by applying an operation to an existing image.
Yeah, it is sure that you have a leak. The object stored previously in the image is not referenced anymore but not deallocated yet

Can any of the iPhone collection objects hold an image?

Actually, I wanted a custom cell which contains 2 image objects and 1 text object, and I decided to make a container for those objects.
So is it possible to hold a image in object and insert that object in any of the collection objects, and later use that object to display inside cell?
NSArray and NSDictionary both hold objects. These are most likely the collections you'll use with a table view.
The best way to implement what you are trying to do is to use the UIImage class. UIImages wrap a CGImage and do all the memory management for you (if your app is running low on memory, the image data is purged and automatically reloaded when you draw it- pretty cool, huh?) You can also read images from files very easily using this class (a whole bunch of formats supported).
Look at the documentation for NSArray, NSMutableArray, and UIImage for more information.
//create a UIImage from a jpeg image
UIImage *myImage = [UIImage imageWithContentsOfFile:#"myImage.jpg"];
NSArray *myArray = [NSMutableArray array]; // this will autorelease, so if you need to keep it around, retain it
[myArray addObject:myImage];
//to draw this image in a UIView's drawRect method
CGContextRef context = UIGraphicsGetCurrentContext(); // you need to find the context to draw into
UIImage *myImage = [myArray lastObject]; // this gets the last object from an array, use the objectAtIndex: method to get a an object with a specific index
CGImageRef *myCGImage = [myImage CGImage];
CGContextDrawImage(context, rect, myCGImage); //rect is passed to drawRect
There should be no problem with that. Just make sure you are properly retaining it and what not in your class.