high memory usage when resizing uiimage - ios

Heavy memory usage when resizing and drawing UIImage in rect.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *selectedImage=[info objectForKey:UIImagePickerControllerOriginalImage];
// COMPRESSING IMAGE
NSData *selectedImageData=UIImageJPEGRepresentation(selectedImage, 0.5);
UIImage *selectedImageFromData=[UIImage imageWithData:selectedImageData];
//SCALING UIIMAGE
UIImage *scaledImage=[[UIImage alloc]init];
if (((selectedImageFromData.size.width>3264) && (selectedImageFromData.size.height>2448)) || ((selectedImageFromData.size.height>3264) && (selectedImageFromData.size.width>2448)))
{
CGFloat originalWidth=selectedImageFromData.size.width;
CGFloat originalHeight=selectedImageFromData.size.height;
CGFloat myWidth=2048;
CGFloat widthRatio=myWidth/originalWidth;
CGFloat dynamicHeight=widthRatio*originalHeight;
CGImageRef CoreGraphicsImage=selectedImageFromData.CGImage;
CGColorSpaceRef colorSpace = CGImageGetColorSpace(CoreGraphicsImage);
CGBitmapInfo bitmapInfo=CGImageGetBitmapInfo(CoreGraphicsImage);
CGImageGetBitsPerComponent(CoreGraphicsImage);
CGContextRef context=CGBitmapContextCreate(NULL, myWidth, dynamicHeight, CGImageGetBitsPerComponent(CoreGraphicsImage), CGImageGetBytesPerRow(CoreGraphicsImage), colorSpace, bitmapInfo);
CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
CGContextDrawImage(context, CGRectMake(0, 0, myWidth, dynamicHeight), CoreGraphicsImage);
CGImageRef CGscaledImage=CGBitmapContextCreateImage(context);
UIImage *CGLastimage = [UIImage imageWithCGImage: CGscaledImage];
NSLog(#"%f",CGLastimage.size.width);
NSLog(#"%f",CGLastimage.size.height);
VisualEffectImageVIew.image=CGLastimage;
BackgroundImageView.image=CGLastimage;
ForegroundImageView.image=CGLastimage;
}
else
{
NSLog(#" HEIGHT %f",selectedImageFromData.size.height);
NSLog(#" WIDTH %f",selectedImageFromData.size.width);
VisualEffectImageVIew.image=selectedImageFromData;
BackgroundImageView.image=selectedImageFromData;
ForegroundImageView.image=selectedImageFromData;
}
if(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone)
{
[picker dismissViewControllerAnimated:YES completion:nil];
}
else
{
[popoverController dismissPopoverAnimated:YES];
[self popoverControllerDidDismissPopover:popoverController];
}
}
Here's an image below, in the image you can see the above mentioned code is using too much memory. Would like to know why it's using too much memory and would appreciate any solutions.

When it comes to images, i've always been a big fan of Brad Larson's GPUImage, it can do anything you want and uses GPU instead of CPU, which leave you with plenty of power to avoid crashes due to memory pressure.
And also it's pretty good.
This stackoverflow question might also help you achieve what you want once you're done setting up the project.
Hope this helps :)

You're using CPU for drawing data into a frame, i suggest you use CGImage for draw in GPU Context
- (UIImage *) scaleToSize: (CGSize)size
{
// Scalling selected image to targeted size
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, size.width, size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
CGContextClearRect(context, CGRectMake(0, 0, size.width, size.height));
if(self.imageOrientation == UIImageOrientationRight)
{
CGContextRotateCTM(context, -M_PI_2);
CGContextTranslateCTM(context, -size.height, 0.0f);
CGContextDrawImage(context, CGRectMake(0, 0, size.height, size.width), self.CGImage);
}
else
CGContextDrawImage(context, CGRectMake(0, 0, size.width, size.height), self.CGImage);
CGImageRef scaledImage=CGBitmapContextCreateImage(context);
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
UIImage *image = [UIImage imageWithCGImage: scaledImage];
CGImageRelease(scaledImage);
return image;
}

Related

Clipping large png make the ios app crash

- (UIImage *)createThumbnailImage:(UIImage *)image withSize:(CGSize)size {
CGRect imageRect = CGRectMake(0.0, 0.0, size.width, size.height);
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, CGRectMake(0, 0, size.width, size.height));
CGContextSetInterpolationQuality(context, 0.8);
[image drawInRect:imageRect blendMode:kCGBlendModeNormal alpha:1];
UIImage *thumbnail = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return thumbnail;
}
- (void)viewDidLoad {
[super viewDidLoad];
UIImage *inputImage = [UIImage imageNamed:#"dog.jpg"];
UIImage *image = [self createThumbnailImage:inputImage withSize:CGSizeMake(640.0, 480.0)]
}
I got a thumbnail image(640 * 480) by code above. And some odd problem confused me.
When I sent a jpg (10000 * 10000) to the method,it worked well.
But when I sent a png with the same size, the app would crash.
I tried to find some documents about the difference between jpg and png, but it made no sense.
Does anyone have any idea about this bug?
-(UIImage *)getNeedImageFrom:(UIImage*)image cropRect:(CGRect)rect
{
CGImageRef subImage = CGImageCreateWithImageInRect(image.CGImage, rect);
UIImage *croppedImage = [UIImage imageWithCGImage:subImage];
CGImageRelease(subImage);
return croppedImage;
}
can you please check if this solve your problem

EXC_BAD_ACCESS error with CGImageRef

I have a function:
- (UIImage *) resizeImage:(UIImage *)image width:(CGFloat)resizedWidth height:(CGFloat)resizedHeight shouldCrop:(BOOL)crop
{
CGImageRef imageRef = [image CGImage];
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bitmap = CGBitmapContextCreate(NULL, resizedWidth, resizedHeight, 8, 4 * resizedWidth, colorSpace, (CGBitmapInfo) kCGImageAlphaPremultipliedFirst);
CGContextDrawImage(bitmap, CGRectMake(0, 0, resizedWidth, resizedHeight), imageRef);
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
if (crop) // for SmallImage (tableviewcell)
{
CGRect cropRect = CGRectMake(0, CGImageGetHeight(ref) * 0.5 - ((float) kIvHeight * 0.5), (float) kIvWidth, (float) kIvHeight);
ref = CGImageCreateWithImageInRect(ref, cropRect);
}
UIImage * result = [UIImage imageWithCGImage:ref];
CGContextRelease(bitmap);
CGImageRelease(ref);
CGImageRelease(imageRef);
return result;
}
The line CGImageRelease(imageRef); causes my app to crash with EXC_BAD_ACCESS
it seems to work when I remove the line - but would this not cause memory leaks?
You don't own the CGImageRef imageRef because you obtain it using [image CGImage] so you don't need to release it.
Take a look at this one as well: How do I release a CGImageRef in iOS

Why does this code resizing an image rotate it 90 degrees from original? [duplicate]

This question already has an answer here:
How to get a correctly rotated UIImage from an ALAssetRepresentation?
(1 answer)
Closed 9 years ago.
I have an iPad app where I'm using the camera. The original image is 480 x 640. I am attempting to resize it to 124 x 160 and then store it in CoreData using this code that I found on the internet:
- (UIImage *)resizeImage:(UIImage*)image newSize:(CGSize)newSize {
CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
CGImageRef imageRef = image.CGImage;
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
// Set the quality level to use when rescaling
CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height);
CGContextConcatCTM(context, flipVertical);
// Draw into the context; this scales the image
CGContextDrawImage(context, newRect, imageRef);
// Get the resized image from the context and a UIImage
CGImageRef newImageRef = CGBitmapContextCreateImage(context);
UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
CGImageRelease(newImageRef);
UIGraphicsEndImageContext();
return newImage;
}
The image is returned to me rotated counter-clockwise 90 degrees and I don't see why. I have tried commenting out this statement:
CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height);
but it makes no difference. What is wrong here?
Thanks to everybody who made suggestions.. I kept looking and found this, which scales and keeps the orientation:
CGRect screenRect = CGRectMake(0, 0, 120.0, 160.0);
UIGraphicsBeginImageContext(screenRect.size);
[image drawInRect:screenRect blendMode:kCGBlendModePlusDarker alpha:1];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
You need to consider the orientation of the image when drawing it like this. Check this answer iOS - UIImageView - how to handle UIImage image orientation

How can I crop an image to have curved irregular edges?

I have UITableViewCell with image in the right size.
This is how the cell should look like:
And i have the backgound:
And the image placeholder:
And i want to know if there is a way to crop image with the iOS library?
Yes that possible:
UIImage *imageToCrop = ...;
UIGraphicsBeginImageContext();
CGContextRef context = UIGraphicsGetCurrentContext();
[imageToCrop drawAtPoint:CGPointZero];
CGContextAddEllipseInRect(context, CGRectMake(0 ,0, imageToCrop.size.width, imageToCrop.size.height);
CGContextClip(context);
UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
You can use CoreGraphics to add mask or clip with path. Mask is image with alpha channel which determines what part of image show. Below example how clip with image mask:
- (UIImage *)croppedImage:(UIImage *)sourceImage
{
UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), NO, [UIScreen mainScreen].scale);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClipToMask(context, CGRectMake(0, 0, width, height), [UIImage imageNamed:#"mask"].CGImage);
[sourceImage drawInRect:CGRectMake(0, 0, width, height)];
UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultImage;
}
Then you can write cell.picture = [self croppedImage:sourceImage];
You can use image masking technique to crop this image
Please have a look at this link
https://developer.apple.com/library/mac/documentation/graphicsimaging/conceptual/drawingwithquartz2d/dq_images/dq_images.html#//apple_ref/doc/uid/TP30001066-CH212-CJBHIJEB
I have written some code that may help you out
#interface ImageRenderer : NSObject {
UIImage *image_;
}
#property (nonatomic, retain) UIImage * image;
- (void)cropImageinRect:(CGRect)rect;
- (void)maskImageWithMask:(UIImage *)maskImage;
- (void)imageWithAlpha;
#end
#implementation ImageRenderer
#synthesize image = image_;
- (void)cropImageinRect:(CGRect)rect {
CGImageRef imageRef = CGImageCreateWithImageInRect(image_.CGImage, rect);
image_ = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
}
- (void)maskImageWithMask:(UIImage *)maskImage {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGImageRef maskImageRef = [maskImage CGImage];
// create a bitmap graphics context the size of the image
CGContextRef mainViewContentContext = CGBitmapContextCreate (NULL, maskImage.size.width, maskImage.size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
if (mainViewContentContext == NULL){
return;
}
CGFloat ratio = 0;
ratio = maskImage.size.width/ image_.size.width;
if(ratio * image_.size.height < maskImage.size.height) {
ratio = maskImage.size.height/ image_.size.height;
}
CGRect rect1 = {{0, 0}, {maskImage.size.width, maskImage.size.height}};
CGRect rect2 = {{-((image_.size.width*ratio)-maskImage.size.width)/2 , -((image_.size.height*ratio)-maskImage.size.height)/2}, {image_.size.width*ratio, image_.size.height*ratio}};
CGContextClipToMask(mainViewContentContext, rect1, maskImageRef);
CGContextDrawImage(mainViewContentContext, rect2, image_.CGImage);
// Create CGImageRef of the main view bitmap content, and then
// release that bitmap context
CGImageRef newImage = CGBitmapContextCreateImage(mainViewContentContext);
CGContextRelease(mainViewContentContext);
image_ = [UIImage imageWithCGImage:newImage];
CGImageRelease(newImage);
}
- (void)imageWithAlpha {
CGImageRef imageRef = image_.CGImage;
CGFloat width = CGImageGetWidth(imageRef);
CGFloat height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(nil, width, height, 8, 0, colorSpace, kCGImageAlphaPremultipliedFirst);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGImageRef resultImageRef = CGBitmapContextCreateImage(context);
image_ = [UIImage imageWithCGImage:resultImageRef scale:image_.scale orientation:image_.imageOrientation];
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
CGImageRelease(resultImageRef);
}
#end
In this code you can crop the image out of a bigger one and then you can use a mask image to get your work done.

quartz 2D image alpha masking

found this little code snippet that seems to do what i want, but im getting yelled at by xcode saying self.CGimage isnt a property of my view controller. (which makes sense since thats a UIimage property). What changes would i need to make to this code for it to be functional? Thanks!
- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {
CGContextRef mainViewContentContext;
CGColorSpaceRef colorSpace;
UIImage* tempImage;
colorSpace = CGColorSpaceCreateDeviceRGB();
// create a bitmap graphics context the size of the image
mainViewContentContext = CGBitmapContextCreate (NULL, image.size.width, image.size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
// free the rgb colorspace
CGColorSpaceRelease(colorSpace);
CGImageRef maskingImage = [maskImage CGImage];
CGContextClipToMask(mainViewContentContext, CGRectMake(0, 0, maskImage.size.width, maskImage.size.height), maskingImage);
CGContextDrawImage(mainViewContentContext, CGRectMake(0, 0, image.size.width, image.size.height), self.CGImage);
// Create CGImageRef of the main view bitmap content, and then
// release that bitmap context
CGImageRef mainViewContentBitmapContext = CGBitmapContextCreateImage(mainViewContentContext);
// convert the finished resized image to a UIImage
UIImage *theImage = [UIImage imageWithCGImage:mainViewContentBitmapContext];
// image is retained by the property setting above, so we can
// release the original
CGContextRelease(mainViewContentContext);
CGImageRelease(mainViewContentBitmapContext);
maskingImage = nil;
CGImageRelease(maskingImage);
// return the image
return theImage;
}
Try replacing self.CGImage with image.CGImage.
Place this method in a UIImage category (or subclass).

Resources