Huge memory peak - CGContextDrawImage

I use this piece of code to scale and rotate images taken with the camera. When I use this, I see a huge peak of memory. Something like 20 MB. When I use the tools, I see that this line:

CGContextDrawImage (ctxt, orig, self.CGImage);

has a value of 20 MB. Is this normal for full resolution photos? The iPhone 4S can handle this. but this code crashes old devices.

After I rescale the image I need in NSData, I use the UIImageJPEGRepresentation () method. This together makes the peak of memory even higher. It takes up to 70 MB in memory in a few seconds.

And yes, I read almost the entire question related to the iOS camera regarding memory usage. But there is no answer.

// WBImage.mm -- extra UIImage methods // by allen brunson march 29 2009 #include "WBImage.h" static inline CGFloat degreesToRadians(CGFloat degrees) { return M_PI * (degrees / 180.0); } static inline CGSize swapWidthAndHeight(CGSize size) { CGFloat swap = size.width; size.width = size.height; size.height = swap; return size; } @implementation UIImage (WBImage) // rotate an image to any 90-degree orientation, with or without mirroring. // original code by kevin lohman, heavily modified by yours truly. // http://blog.logichigh.com/2008/06/05/uiimage-fix/ -(UIImage*)rotate:(UIImageOrientation)orient { CGRect bnds = CGRectZero; UIImage* copy = nil; CGContextRef ctxt = nil; CGRect rect = CGRectZero; CGAffineTransform tran = CGAffineTransformIdentity; bnds.size = self.size; rect.size = self.size; switch (orient) { case UIImageOrientationUp: return self; case UIImageOrientationUpMirrored: tran = CGAffineTransformMakeTranslation(rect.size.width, 0.0); tran = CGAffineTransformScale(tran, -1.0, 1.0); break; case UIImageOrientationDown: tran = CGAffineTransformMakeTranslation(rect.size.width, rect.size.height); tran = CGAffineTransformRotate(tran, degreesToRadians(180.0)); break; case UIImageOrientationDownMirrored: tran = CGAffineTransformMakeTranslation(0.0, rect.size.height); tran = CGAffineTransformScale(tran, 1.0, -1.0); break; case UIImageOrientationLeft: bnds.size = swapWidthAndHeight(bnds.size); tran = CGAffineTransformMakeTranslation(0.0, rect.size.width); tran = CGAffineTransformRotate(tran, degreesToRadians(-90.0)); break; case UIImageOrientationLeftMirrored: bnds.size = swapWidthAndHeight(bnds.size); tran = CGAffineTransformMakeTranslation(rect.size.height, rect.size.width); tran = CGAffineTransformScale(tran, -1.0, 1.0); tran = CGAffineTransformRotate(tran, degreesToRadians(-90.0)); break; case UIImageOrientationRight: bnds.size = swapWidthAndHeight(bnds.size); tran = CGAffineTransformMakeTranslation(rect.size.height, 0.0); tran = CGAffineTransformRotate(tran, degreesToRadians(90.0)); break; case UIImageOrientationRightMirrored: bnds.size = swapWidthAndHeight(bnds.size); tran = CGAffineTransformMakeScale(-1.0, 1.0); tran = CGAffineTransformRotate(tran, degreesToRadians(90.0)); break; default: // orientation value supplied is invalid assert(false); return nil; } UIGraphicsBeginImageContext(rect.size); ctxt = UIGraphicsGetCurrentContext(); switch (orient) { case UIImageOrientationLeft: case UIImageOrientationLeftMirrored: case UIImageOrientationRight: case UIImageOrientationRightMirrored: CGContextScaleCTM(ctxt, -1.0, 1.0); CGContextTranslateCTM(ctxt, -rect.size.height, 0.0); break; default: CGContextScaleCTM(ctxt, 1.0, -1.0); CGContextTranslateCTM(ctxt, 0.0, -rect.size.height); break; } CGContextConcatCTM(ctxt, tran); CGContextDrawImage(ctxt, bnds, self.CGImage); copy = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return copy; } -(UIImage*)rotateAndScaleFromCameraWithMaxSize:(CGFloat)maxSize { UIImage* imag = self; imag = [imag rotate:imag.imageOrientation]; imag = [imag scaleWithMaxSize:maxSize]; return imag; } -(UIImage*)scaleWithMaxSize:(CGFloat)maxSize { return [self scaleWithMaxSize:maxSize quality:kCGInterpolationHigh]; } -(UIImage*)scaleWithMaxSize:(CGFloat)maxSize quality:(CGInterpolationQuality)quality { CGRect bnds = CGRectZero; UIImage* copy = nil; CGContextRef ctxt = nil; CGRect orig = CGRectZero; CGFloat rtio = 0.0; CGFloat scal = 1.0; bnds.size = self.size; orig.size = self.size; rtio = orig.size.width / orig.size.height; if ((orig.size.width <= maxSize) && (orig.size.height <= maxSize)) { return self; } if (rtio > 1.0) { bnds.size.width = maxSize; bnds.size.height = maxSize / rtio; } else { bnds.size.width = maxSize * rtio; bnds.size.height = maxSize; } UIGraphicsBeginImageContext(bnds.size); ctxt = UIGraphicsGetCurrentContext(); scal = bnds.size.width / orig.size.width; CGContextSetInterpolationQuality(ctxt, quality); CGContextScaleCTM(ctxt, scal, -scal); CGContextTranslateCTM(ctxt, 0.0, -orig.size.height); CGContextDrawImage(ctxt, orig, self.CGImage); copy = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return copy; } @end 
+4
source share
3 answers

I ended up using imageIO, less memory!

 -(UIImage *)resizeImageToMaxDimension: (float) dimension withPaht: (NSString *)path { NSURL *imageUrl = [NSURL fileURLWithPath:path]; CGImageSourceRef imageSource = CGImageSourceCreateWithURL((__bridge CFURLRef)imageUrl, NULL); NSDictionary *thumbnailOptions = [NSDictionary dictionaryWithObjectsAndKeys: (id)kCFBooleanTrue, kCGImageSourceCreateThumbnailWithTransform, kCFBooleanTrue, kCGImageSourceCreateThumbnailFromImageAlways, [NSNumber numberWithFloat:dimension], kCGImageSourceThumbnailMaxPixelSize, nil]; CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, (__bridge CFDictionaryRef)thumbnailOptions); UIImage *resizedImage = [UIImage imageWithCGImage:thumbnail]; CFRelease(thumbnail); CFRelease(imageSource); return resizedImage; } 
+2
source


that this comes from the image that you shot with your camera, older devices use lower resolution cameras, which means that the images taken with the iPhone 3g are smaller in resolution (thus the size) matches the one you on your iPhone4. Images are usually compressed, but when they open in memory for some operation, they should be unpacked, the size that they need is really bigger than the one in the file, because it's number_of_pixel_in_row*number_of_pixel_in_height*byte_for_pixel , if I'm good I remember. Goodbye, Andrea

+1
source

Insert this at the end of your methods and before return copy; :

 CGContextRelease(ctxt); 
0
source

Source: https://habr.com/ru/post/1397638/


All Articles