10

有没有人可以帮我解决这个问题我对目标C和iOS有点新。我一直在努力,但我无法弄清楚如何解决这个问题,我的应用程序非常简单,它只启动相机拍照并通过电子邮件发送给我们的服务器。这段代码在iOS6中工作得很好。内存警告UIImagepickerController IOS 7

当我拍照时,我的记忆是每个屏幕捕捉的堆积增长,并且我收到“接收到的内存警告”,最后 - 由于内存压力而终止。 -

-(void)imagePickerController:(UIImagePickerController *)picker 
didFinishPickingMediaWithInfo:(NSDictionary *)info 
{ 

[self.popoverController2 dismissPopoverAnimated:true]; 
NSString *mediaType = [info 
         objectForKey:UIImagePickerControllerMediaType]; 

if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) { 
    _image = [info 
         objectForKey:UIImagePickerControllerOriginalImage]; 

    _image = [self fixrotation:_image]; //<----- increased memory when UIImageWriteToSavedPhotosAlbum is uncommented IF is comment it doesn't increased memory but after some pictures I start to get "Received Memory Warning" message until the app Crash. 

    if (_newMedia){ 
     UIImageWriteToSavedPhotosAlbum(_image, 
             self,@selector(image:finishedSavingWithError:contextInfo:), 
             nil); 
    [self dismissViewControllerAnimated:NO completion:nil]; 
    [self performSegueWithIdentifier:@"SeleccionadoCameraR" sender:self]; 


    }else{ 
     [self performSegueWithIdentifier:@"SeleccionadoCameraR" sender:self]; 

    } 

} 

} 

- (UIImage *)fixrotation:(UIImage *)image{ 


if (image.imageOrientation == UIImageOrientationUp) return image; 
CGAffineTransform transform = CGAffineTransformIdentity; 

switch (image.imageOrientation) { 
    case UIImageOrientationDown: 
    case UIImageOrientationDownMirrored: 
     transform = CGAffineTransformTranslate(transform, image.size.width, image.size.height); 
     transform = CGAffineTransformRotate(transform, M_PI); 
     break; 

    case UIImageOrientationLeft: 
    case UIImageOrientationLeftMirrored: 
     transform = CGAffineTransformTranslate(transform, image.size.width, 0); 
     transform = CGAffineTransformRotate(transform, M_PI_2); 
     break; 

    case UIImageOrientationRight: 
    case UIImageOrientationRightMirrored: 
     transform = CGAffineTransformTranslate(transform, 0, image.size.height); 
     transform = CGAffineTransformRotate(transform, -M_PI_2); 
     break; 
    case UIImageOrientationUp: 
    case UIImageOrientationUpMirrored: 
     break; 
} 

switch (image.imageOrientation) { 
    case UIImageOrientationUpMirrored: 
    case UIImageOrientationDownMirrored: 
     transform = CGAffineTransformTranslate(transform, image.size.width, 0); 
     transform = CGAffineTransformScale(transform, -1, 1); 
     break; 

    case UIImageOrientationLeftMirrored: 
    case UIImageOrientationRightMirrored: 
     transform = CGAffineTransformTranslate(transform, image.size.height, 0); 
     transform = CGAffineTransformScale(transform, -1, 1); 
     break; 
    case UIImageOrientationUp: 
    case UIImageOrientationDown: 
    case UIImageOrientationLeft: 
    case UIImageOrientationRight: 
     break; 
} 

// Now we draw the underlying CGImage into a new context, applying the transform 
// calculated above. 
CGContextRef ctx = CGBitmapContextCreate(NULL, image.size.width, image.size.height, 
             CGImageGetBitsPerComponent(image.CGImage), 0, 
             CGImageGetColorSpace(image.CGImage), 
             CGImageGetBitmapInfo(image.CGImage)); 


CGContextConcatCTM(ctx, transform); 
switch (image.imageOrientation) { 
    case UIImageOrientationLeft: 
    case UIImageOrientationLeftMirrored: 
    case UIImageOrientationRight: 
    case UIImageOrientationRightMirrored: 
     // Grr... 
     CGContextDrawImage(ctx, CGRectMake(0,0,image.size.height,image.size.width), image.CGImage); 
     break; 

    default: 
     CGContextDrawImage(ctx, CGRectMake(0,0,image.size.width,image.size.height), image.CGImage); //when I use instruments it shows that My VM is because of this 
     break; 
} 

// And now we just create a new UIImage from the drawing context 
CGImageRef cgimg = CGBitmapContextCreateImage(ctx);//also this line in Instruments 
UIImage *img = [UIImage imageWithCGImage:cgimg]; 


CGContextRelease(ctx); 
CGImageRelease(cgimg); 


return img; 


} 

可能是内存管理。我会感谢您的帮助

+0

运行静态分析器查看是否有任何警告。然后在乐器中运行应用程序,查找任何泄漏并保留周期。 – rmaddy

回答

7

你正处于正确的轨道与你的fixRotation方法。不过,您还应该调整大小的形象。否则,图像会很大,〜30 MB(取决于设备)。

结帐this blog post如何正确调整图像大小。具体而言,您希望UIImage类文件是这些:

UIImage+Resize.h

UIImage+Resize.m

这也是一个好主意,这样做在后台线程。这样

- (void)imagePickerController:(UIImagePickerController *)imagePicker didFinishPickingMediaWithInfo:(NSDictionary *)info 
{ 
    // Dismiss the image picker first to free its memory 
    [self dismissViewControllerAnimated:YES completion:nil]; 

    UIImage *originalImage = info[UIImagePickerControllerOriginalImage]; 

    if (!originalImage) 
     return; 

    // Optionally set a placeholder image here while resizing happens in background 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

     // Set desired maximum height and calculate width 
     CGFloat height = 640.0f; // or whatever you need 
     CGFloat width = (height/originalImage.size.height) * originalImage.size.width; 

     // Resize the image 
     UIImage * image = [originalImage resizedImage:CGSizeMake(width, height) interpolationQuality:kCGInterpolationDefault]; 

     // Optionally save the image here... 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      // ... Set/use the image here... 
     });   
    }); 
} 
+0

我已调整大小,内存增加减少,但它继续增加一点点,直到我的应用程序崩溃,以某种方式,我需要清除内存 –

+0

首先,我说了一个新的项目与iOS7具有相同的类和方法,最后我将图像大小调整为640 x 480和480 x 640,然后应用了fixRotation方法,我的记忆增加了一次,但与其他照片没有增加。 –

+0

@cesartrujillocetina你能展示你的最终工作代码吗?我有同样的问题。 – Danpe

4

UIImageWriteToSavedPhotosAlbum方法使用30M +内存iOS7.It东西不是你的大小或fixrotation方法。

+0

我有同样的问题,并调整图像doens't工作... – Ladessa

+0

我也有同样的问题..是任何一个得到的解决方案? – Sabareesh

+0

是的,每当我打电话给UIImageWriteToSavedPhotosAlbum时,我的应用程序都会收到内存警告!而且显然崩溃! –

1

我已经JRG-开发-S答案在这里 少许改动修复了这个问题: 我`使用类别来修复图像的方向中号ANS呈现 之前比例缩小完成后,我打电话弱自我此缩放和定影图像分配到我的ImageView)

-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
{  
    UIImage *lvImage = [info objectForKey:UIImagePickerControllerOriginalImage]; 
    //CGSize pickedImageSize = lvImage.size; 
    if (postHandler == nil) 
    { 
     postHandler = [[PostHandler alloc] init]; 
    } 

    //_postItemImageView.image = lvImage; 
    //postHandler.wholeScreenImage = lvImage;// to proceed editing, cropping, tagging ... 
    //_postItemImageView.image = postHandler.wholeScreenImage; set in viewWillAppear 
    __weak PostPrepareViewController *weakSelf = self; 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^
    { 

     // Resize the image 
     UIImage * scaledImage = [[lvImage imageByScalingAndCroppingForSize:_postItemImageView.frame.size] fixOrientation]; 
     // Optionally save the image here... 
     //CGSize scaledimageSize = scaledImage.size; 
     dispatch_async(dispatch_get_main_queue(),^
     { 
      postHandler.wholeScreenImage = scaledImage; 
      [weakSelf didScaleDownImage]; 
     });   
    }); 


    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) 
    { 
     [self.popOver dismissPopoverAnimated:YES]; 
    } 
    else 
    { 
     [self dismissViewControllerAnimated:YES completion:nil]; 
    } 
} 

和下:

-(void) didScaleDownImage 
{ 
    _postItemImageView.image = postHandler.wholeScreenImage; 
} 

缩放的代码从净采取:

-(UIImage *)imageByScalingAndCroppingForSize:(CGSize)targetSize 
{ 
    UIImage *sourceImage = self; 
    UIImage *newImage = nil; 
    CGSize imageSize = sourceImage.size; 
    CGFloat width = imageSize.width; 
    CGFloat height = imageSize.height; 
    CGFloat targetWidth = targetSize.width; 
    CGFloat targetHeight = targetSize.height; 
    CGFloat scaleFactor = 0.0; 
    CGFloat scaledWidth = targetWidth; 
    CGFloat scaledHeight = targetHeight; 
    CGPoint thumbnailPoint = CGPointMake(0.0,0.0); 

    if (CGSizeEqualToSize(imageSize, targetSize) == NO) 
    { 
     CGFloat widthFactor = targetWidth/width; 
     CGFloat heightFactor = targetHeight/height; 

     if (widthFactor > heightFactor) 
     { 
      scaleFactor = widthFactor; // scale to fit height 
     } 
     else 
     { 
      scaleFactor = heightFactor; // scale to fit width 
     } 

     scaledWidth = width * scaleFactor; 
     scaledHeight = height * scaleFactor; 

     // center the image 
     if (widthFactor > heightFactor) 
     { 
      thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 
     } 
     else 
     { 
      if (widthFactor < heightFactor) 
      { 
       thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5; 
      } 
     } 
    } 

    UIGraphicsBeginImageContext(targetSize); // this will crop 
    //UIGraphicsBeginImageContextWithOptions(targetSize, 1.0, 0.0); 

    CGRect thumbnailRect = CGRectZero; 
    thumbnailRect.origin = thumbnailPoint; 
    thumbnailRect.size.width = scaledWidth; 
    thumbnailRect.size.height = scaledHeight; 

    [sourceImage drawInRect:thumbnailRect]; 

    newImage = UIGraphicsGetImageFromCurrentImageContext(); 

    if(newImage == nil) 
    { 
     NSLog(@"could not scale image"); 
    } 

    //pop the context to get back to the default 
    UIGraphicsEndImageContext(); 

    return newImage; 
} 

,并改变(固定)图像取向也采取从网上代码:

- (UIImage *)fixOrientation 
{ // No-op if the orientation is already correct 
    if (self.imageOrientation == UIImageOrientationUp) return self; 

    // We need to calculate the proper transformation to make the image upright. 
    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored. 
    CGAffineTransform transform = CGAffineTransformIdentity; 

    switch (self.imageOrientation) { 
     case UIImageOrientationDown: 
     case UIImageOrientationDownMirrored: 
      transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height); 
      transform = CGAffineTransformRotate(transform, M_PI); 
      break; 

     case UIImageOrientationLeft: 
     case UIImageOrientationLeftMirrored: 
      transform = CGAffineTransformTranslate(transform, self.size.width, 0); 
      transform = CGAffineTransformRotate(transform, M_PI_2); 
      break; 

     case UIImageOrientationRight: 
     case UIImageOrientationRightMirrored: 
      transform = CGAffineTransformTranslate(transform, 0, self.size.height); 
      transform = CGAffineTransformRotate(transform, -M_PI_2); 
      break; 

     default: 
      break; 
    } 

    switch (self.imageOrientation) { 
     case UIImageOrientationUpMirrored: 
     case UIImageOrientationDownMirrored: 
      transform = CGAffineTransformTranslate(transform, self.size.width, 0); 
      transform = CGAffineTransformScale(transform, -1, 1); 
      break; 

     case UIImageOrientationLeftMirrored: 
     case UIImageOrientationRightMirrored: 
      transform = CGAffineTransformTranslate(transform, self.size.height, 0); 
      transform = CGAffineTransformScale(transform, -1, 1); 
      break; 

     default: 
      break; 
    } 

    // Now we draw the underlying CGImage into a new context, applying the transform 
    // calculated above. 
    CGContextRef ctx = CGBitmapContextCreate(NULL, self.size.width, self.size.height, 
              CGImageGetBitsPerComponent(self.CGImage), 0, 
              CGImageGetColorSpace(self.CGImage), 
              CGImageGetBitmapInfo(self.CGImage)); 
    CGContextConcatCTM(ctx, transform); 
    switch (self.imageOrientation) { 
     case UIImageOrientationLeft: 
     case UIImageOrientationLeftMirrored: 
     case UIImageOrientationRight: 
     case UIImageOrientationRightMirrored: 
      // Grr... 
      CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage); 
      break; 

     default: 
      CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.CGImage); 
      break; 
    } 

    // And now we just create a new UIImage from the drawing context 
    CGImageRef cgimg = CGBitmapContextCreateImage(ctx); 
    CGContextRelease(ctx); 
    UIImage *img = [UIImage imageWithCGImage:cgimg]; 

    CGImageRelease(cgimg); 
    // 
    return img; 
} 

请不要-T是残酷的minusing如果事情看起来虚拟)林初中现在)

对于下面的答案 - 这就是为什么你会更好地缩小图像 - 使用较少的内存,但不是简单地将大4MB图像保存到光盘。在刚开始的时候,我也有记忆问题 - 每张单张照片吃了30Mb - 我不得不逐一拍摄2张照片......现在它工作得很好,很顺利。 修复方向是可选的,但我会建议无论如何缩小照片 - 调整到较小。