Ios CGImageSourceCreateTumbnailAtIndex因20MB图像而崩溃
当我用大图像(即>10MB)测试iPad时,以下创建缩略图的方法会在iPad上崩溃。我已经对它进行了分析,分配没有报告任何大的内存峰值-在操作期间,它始终保持5 MB的活动内存 如何为如此大的图像创建缩略图?我尝试过用核心图形来扩展它,但内存效率较低,不起作用Ios CGImageSourceCreateTumbnailAtIndex因20MB图像而崩溃,ios,objective-c,image,Ios,Objective C,Image,当我用大图像(即>10MB)测试iPad时,以下创建缩略图的方法会在iPad上崩溃。我已经对它进行了分析,分配没有报告任何大的内存峰值-在操作期间,它始终保持5 MB的活动内存 如何为如此大的图像创建缩略图?我尝试过用核心图形来扩展它,但内存效率较低,不起作用 +(UIImage*) thumbnailImageAtPath:(NSString*) path withSize:(CGSize) size{ @autoreleasepool{ CGImageSource
+(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的PDF文件中工作得非常出色。尝试删除选项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;}
我想我知道问题出在哪里了
我使用的png中有相当多的alpha透明像素
不过,我必须对不同的alpha/non-alpha图像运行一些确定的测试,以确认这就是问题所在。当我有机会时,我会这样做。这不起作用-它继续崩溃,并为加载的所有其他缩略图发出内存警告。几个问题1)到底是什么崩溃?2) 你能主持一个有问题的图像吗?我手头没有任何超大图像3)什么设备和iOS版本?谢谢1) 它只是停止-没有内存警告或异常2)任何图像在访问10MB时都会出现问题。。试试这一款iPadMiniOS6,我应该注意,我只在这台设备和模拟器上试过,因为这是应用程序运行的最低规格设备,在iPadMiniOS6.1.3上运行这一代码,使用这张图片,效果很好。我正在传递一个
{100100}
的大小。你能解释一下上下文吗?你能用“只是停一下”来解释更多吗?它挂起来了吗?是否生成了任何崩溃日志?编辑:我应该注意到墙纸只有10兆。我正在寻找一个更大的,但如果你能主办一个将是一个帮助。谢谢你,还有一个更新——我在维基百科上找到了一个18MB的jpg。到目前为止,100*100、40*40和20*20的传球速度似乎较慢,但没有发生碰撞或悬挂。当然,现在我仔细看看代码,它只记录大小。我认为你的问题中缺少了一些有助于重现问题的上下文。没有日志,没有挂起,什么都没有。它只是停止了。我已经分析过了,仪器中没有异常的记忆尖峰。我已经通过了200x200和100x100两种尺寸的测试,但都崩溃了。在上下文方面:它是一个PNG文件(这会有什么不同吗?),在操作中调用“缩略图创建”方法,并在非并发后台队列中运行。我必须这样做,因为如果我在主线程上生成缩略图,UI将挂起。谢谢您的帮助,顺便说一下:)这不是内存效率,因为您正在将整个图像加载到内存中。
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;
}