CGImageSourceCreateThumbnailAtIndex与20MB图像崩溃

时间:2013-09-12 17:42:31

标签: ios objective-c image

当我使用大图像(即> 10 MB)测试时,以下创建缩略图图像的方法在iPad上崩溃。我已经对它进行了分析,Allocations没有报告任何大的内存峰值 - 它在运行期间始终保持5 MB的活动内存。

如何为图片创建如此大的缩略图?我已尝试使用Core Graphics进行扩展,但这样会降低内存效率并且不起作用。

+(UIImage*) thumbnailImageAtPath:(NSString*) path withSize:(CGSize) size{

    @autoreleasepool{

        CGImageSourceRef src = CGImageSourceCreateWithURL((__bridge CFURLRef)[NSURL fileURLWithPath:path], NULL);

        if(!src){
            return nil;
        }

        NSDictionary* options = @{
                                  (id)kCGImageSourceShouldAllowFloat : (id)kCFBooleanTrue,
                                  (id)kCGImageSourceCreateThumbnailWithTransform : (id)kCFBooleanFalse,
                                  (id)kCGImageSourceCreateThumbnailFromImageIfAbsent : (id)kCFBooleanTrue,
                                  (id)kCGImageSourceThumbnailMaxPixelSize : [NSNumber numberWithDouble:1024]
                                  };

        CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, (__bridge CFDictionaryRef)options);

        // Doesn't reach here :(

        UIImage* img = [[UIImage alloc] initWithCGImage:thumbnail];

        NSLog(@"Size: %f, %f", size.width, size.height);

        CGImageRelease(thumbnail);
        CFRelease(src);

        return img;

    }

}

我已经在主线程,工作线程,并发,非并发等上尝试过它 - 它似乎在实际设备上不起作用。

奇怪的是,它的工作效果非常出色。 60 MB。

3 个答案:

答案 0 :(得分:0)

尝试删除选项kCGImageSourceThumbnailMaxPixelSize ...如果没有请问我。

编辑: 试试这段代码:

+ (UIImage*)scaleAndRotateImage:(UIImage *)image{

int kMaxResolution = 1024; // Or whatever 320

CGImageRef imgRef = image.CGImage;

CGFloat width;
CGFloat height;

width = CGImageGetWidth(imgRef);
height = CGImageGetHeight(imgRef);

CGAffineTransform transform = CGAffineTransformIdentity;
CGRect bounds = CGRectMake(0, 0, width, height);
if (width > kMaxResolution || height > kMaxResolution) {
    CGFloat ratio = width/height;
    if (ratio > 1) {
        bounds.size.width = kMaxResolution;
        bounds.size.height = bounds.size.width / ratio;
    }
    else {
        bounds.size.height = kMaxResolution;
        bounds.size.width = bounds.size.height * ratio;
    }
}

CGFloat scaleRatio = bounds.size.width / width;
CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
CGFloat boundHeight;
UIImageOrientation orient = image.imageOrientation;
switch(orient) {

    case UIImageOrientationUp: //EXIF = 1
        transform = CGAffineTransformIdentity;
        break;

    case UIImageOrientationUpMirrored: //EXIF = 2
        transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
        transform = CGAffineTransformScale(transform, -1.0, 1.0);
        break;

    case UIImageOrientationDown: //EXIF = 3
        transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
        transform = CGAffineTransformRotate(transform, M_PI);
        break;

    case UIImageOrientationDownMirrored: //EXIF = 4
        transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
        transform = CGAffineTransformScale(transform, 1.0, -1.0);
        break;

    case UIImageOrientationLeftMirrored: //EXIF = 5
        boundHeight = bounds.size.height;
        bounds.size.height = bounds.size.width;
        bounds.size.width = boundHeight;
        transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
        transform = CGAffineTransformScale(transform, -1.0, 1.0);
        transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
        break;

    case UIImageOrientationLeft: //EXIF = 6
        boundHeight = bounds.size.height;
        bounds.size.height = bounds.size.width;
        bounds.size.width = boundHeight;
        transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
        transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
        break;

    case UIImageOrientationRightMirrored: //EXIF = 7
        boundHeight = bounds.size.height;
        bounds.size.height = bounds.size.width;
        bounds.size.width = boundHeight;
        transform = CGAffineTransformMakeScale(-1.0, 1.0);
        transform = CGAffineTransformRotate(transform, M_PI / 2.0);
        break;

    case UIImageOrientationRight: //EXIF = 8
        boundHeight = bounds.size.height;
        bounds.size.height = bounds.size.width;
        bounds.size.width = boundHeight;
        transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
        transform = CGAffineTransformRotate(transform, M_PI / 2.0);
        break;

    default:
        [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];

}

UIGraphicsBeginImageContext(bounds.size);

CGContextRef context = UIGraphicsGetCurrentContext();

if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
    CGContextScaleCTM(context, -scaleRatio, scaleRatio);
    CGContextTranslateCTM(context, -height, 0);
}
else {
    CGContextScaleCTM(context, scaleRatio, -scaleRatio);
    CGContextTranslateCTM(context, 0, -height);
}

CGContextConcatCTM(context, transform);

CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

return imageCopy;}

答案 1 :(得分:0)

认为我知道这是什么问题。

我使用的png中有很多alpha透明像素。

但是,我必须使用不同的alpha / non-alpha图像运行一些确定的测试,以确认这是问题所在。当我有机会的时候会这样做。

答案 2 :(得分:-1)

NSString *path = [[NSBundle mainBundle] pathForResource:@"LARGE_elevation" ofType:@"jpg"];

UIImage* image = [UIImage imageWithContentsOfFile:path];
image = [self scaleImage:image toSize:CGSizeMake(400, 200)];

- (UIImage *)scaleImage:(UIImage *)image
                        toSize:(CGSize)size
{
    CGSize sz = image.size;
    if(sz.width > size.width || sz.height > size.height) {
        double ratio = MIN(sz.width / size.width, sz.height / size.height);
        sz.width /= ratio;
        sz.height /= ratio;
    }
    CGContextRef context;
    UIGraphicsBeginImageContextWithOptions(size, NO, image.scale);
    context = UIGraphicsGetCurrentContext();
    CGContextSetGrayFillColor(context, 0.0, 1.0);
    CGContextFillRect(context, CGRectMake(0, 0, size.width, size.height));
    [image drawInRect:CGRectMake(0, 0, sz.width, sz.height)];
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

LARGE_elevation.jpg - 14.3 mb。