代码之家  ›  专栏  ›  技术社区  ›  cesar trujillo cetina

内存警告UIImagepickerController IOS 7

  •  10
  • cesar trujillo cetina  · 技术社区  · 12 年前

    有人能帮我解决这个问题吗?我对objective c和iOS有点陌生。我一直在努力,但我不知道如何解决这个问题,我的应用程序非常简单,它只启动相机拍照并通过电子邮件发送到我们的服务器。这个代码在iOS6中运行得很好。

    当我拍照时,我的内存随着每次屏幕捕捉而堆积增长,我会收到“收到内存警告”,最后——由于内存压力而终止-

    -(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;
    
    
     }
    

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

    3 回复  |  直到 12 年前
        1
  •  7
  •   JRG-Developer    10 年前

    你走在了正确的轨道上 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...
            });           
        });
    }
    
        2
  •  4
  •   patgdut    12 年前

    UIImageWriteToSavedPhotsAlbum方法在iOS7上使用30M以上的内存。这与调整大小或修复旋转方法无关。

        3
  •  1
  •   Massmaker    12 年前

    我已经通过JRG-Developers在这里的回答解决了这个问题 稍作修改: 我正在使用类别来固定图像的方向,并在呈现之前缩小它 完成后,我会调用弱自我,将这个缩放的固定图像分配给我的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;
    }
    

    请,如果有东西看起来很假,不要吝啬)我现在是初级)

    对于下面的答案——这就是为什么你最好缩小图像的比例——以减少使用中的内存,但不要简单地将4MB的大图像保存到光盘上。一开始我也有记忆力问题——每张照片要吃掉30Mb——我不得不一张接一张地拍两张照片。。。现在它工作得很好,很顺利。 修复方向是可选的,但我还是建议缩小照片的比例,将其调整到更小的尺寸。

    推荐文章