10

有人可以帮我解决这个问题吗?我对目标 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;


 }

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

4

3 回答 3

7

你用你的fixRotation方法走在正确的轨道上。但是,您还应该调整图像的大小。否则,图像会很大,大约 30 MB(取决于设备)。

查看这篇关于如何正确调整图像大小的博客文章。具体来说,UIImage您想要的类别文件是:

UIImage+调整大小.h

UIImage+调整大小.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...
        });           
    });
}
于 2013-09-27T23:47:47.073 回答
4

UIImageWriteToSavedPhotosAlbum 方法在 iOS7 上使用 30M+ 内存。这与您的调整大小或固定旋转方法无关。

于 2013-10-25T10:22:35.960 回答
1

我已经通过 JRG-Developer-s 解决了这个问题,在这里做了一些修改:我使用类别来修复图像的方向并在呈现之前缩小它,完成后,我调用 Wea​​k Self 来分配这个缩放和固定的图像到我的图像视图)

-(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——我不得不一张一张地拍两张……现在它工作得很好而且很流畅。固定方向是可选的,但我还是建议按比例缩小照片 - 将其调整为更小。

于 2014-02-18T09:23:34.357 回答