【问题标题】:iPhone iOS's image resize for lowest memory usage solutioniPhone iOS 的图像调整大小以实现最低内存使用解决方案
【发布时间】:2012-10-30 14:27:10
【问题描述】:

我从大约 8MP 的原始分辨率图像调整图像大小,我的输出分辨率约为 2MP。 有时,它会显示 iPhone4S 设备的内存警告,我在 memorywarning 中做了一些释放,但它有时会使我的程序因 alassetlibrary 使用问题而崩溃。 这是我的问题,我想在调整 fullReoslutionImage 大小时防止出现内存警告。

我尝试了许多调整图像大小的方法。 我目前的方法是峰值内存使用量增加约 44MB。它似乎太大了......对于整个系统来说,它会有一个 57 MB 的峰值...... 我尝试了 CGImageSourceCreateThumbnailAtIndex,但它比我当前的方法增加了更多的内存。

这是我的解决方案,但有时仍会引入内存警告。你有其他方法吗? 你可以帮帮我吗?一些想法, 1. 其他iOS API? 2. JPEG 解码器动态调整大小的原生库? 3. YUV422调整大小而不是RGBA。 4.......我不知道......

UIImage *image=[self oriImageThumbnailAtIndex:asset];
        CGInterpolationQuality interpolationQuality=kCGInterpolationMedium;            
        CGSize newSize=[self sizeDown:image.size];            
        image2 =makeResizedImageRotate(image, newSize, interpolationQuality,[defaultRep orientation]);


-(UIImage *) oriImageThumbnailAtIndex:(ALAsset *)asset
{
int times=0;
ALAssetRepresentation* assetRepresentation=asset.defaultRepresentation;
long long imageDataSize = [assetRepresentation size];    
uint8_t* imageDataBytes = (uint8_t*) malloc(imageDataSize);
[assetRepresentation getBytes:imageDataBytes fromOffset:0 length:imageDataSize error:nil];
NSData *data = [NSData dataWithBytesNoCopy:imageDataBytes length:imageDataSize freeWhenDone:YES];
UIImage *image2=nil;  
CGImageSourceRef src = CGImageSourceCreateWithData((__bridge CFDataRef) data, NULL);        
CGImageRef thumbnail;
if (src)
{
    float _maxSize=RESIZE_IMAGE_BIG_SIDE;
    thumbnail = CGImageSourceCreateImageAtIndex(src, 0, NULL); // Create scaled image
    image2 = [UIImage imageWithCGImage:thumbnail];        
    CGImageRelease(thumbnail);        
}else{
    NSLog(@"resizeImage:(ALAsset *)asset error!!!");        
}

return image2;
}

UIImage* makeResizedImageRotate(UIImage *inimage,CGSize newSize,CGInterpolationQuality interpolationQuality,UIImageOrientation orient) {
CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
CGImageRef imageRef = inimage.CGImage;

// Compute the bytes per row of the new image
size_t bytesPerRow = CGImageGetBitsPerPixel(imageRef) / CGImageGetBitsPerComponent(imageRef) * newRect.size.width;
bytesPerRow = (bytesPerRow + 15) & ~15;  // Make it 16-byte aligned
  CGBitmapInfo cgbmpinfo=CGImageGetBitmapInfo(imageRef);
CGContextRef bitmap = CGBitmapContextCreate(NULL,
                                            newRect.size.width,
                                            newRect.size.height,
                                            CGImageGetBitsPerComponent(imageRef),
                                            bytesPerRow,
                                            CGImageGetColorSpace(imageRef),
                                            cgbmpinfo);
if(bitmap!=nil)
    CGContextSetInterpolationQuality(bitmap, interpolationQuality);
else
    NSLog(@"bitmap==nil");


// Draw into the context; this scales the image
CGContextDrawImage(bitmap, newRect, imageRef);

// Get the resized image from the context and a UIImage
CGImageRef resizedImageRef = CGBitmapContextCreateImage(bitmap);
UIImage *resizedImage = [UIImage imageWithCGImage:resizedImageRef];
CGContextRelease(bitmap);
CGImageRelease(resizedImageRef);
resizedImage=rotateImage( resizedImage, orient);
// Clean up

// [resizedImage autorelease]; will introduce BAD_ADDRESS
return resizedImage;

}

【问题讨论】:

  • 我刚试过libjpeg-turbo,速度够快,而且它可以支持在解码JPEG时调整大小。但是,它似乎只支持 1/2、1/4、1/8 下采样率,我需要的是大约 >=0.55(从 3264 到 1800),所以它无法达到我的目标....仍在寻找解决方案....任何JPEG解码器都可以支持合理比率下采样吗?
  • libjpeg-turbo.sourceforge.net/ljt.nightly 作者告诉我这个 libjpeg-turbo 的二进制版本可以支持更多的缩放因子。它可以支持 16 个缩放因子。也许有人会需要它。

标签: iphone ios memory resize


【解决方案1】:

我正在使用下面的代码

-(UIImage*) generateThumbnailFromImage:(UIImage*)mainImage
{
    UIImage * thumbnail;

    CGSize destinationSize = CGSizeMake(thumbnail image width,thumbnail image height);

    UIGraphicsBeginImageContext(destinationSize);
    [mainImage drawInRect:CGRectMake(0,0,destinationSize.width, destinationSize.height)];
    thumbnail = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return thumbnail;
}

我从来没有遇到过内存警告,尝试一下它是如何与你的代码一起工作的。

【讨论】:

  • 非常感谢。我试过了,但它增加了大约 58MB,峰值增加了 71MB。所以,它似乎不会减少内存使用量。我的另一个问题是为什么我很容易收到 ipad2 和 iphone4s 的内存警告,但很少收到 iphone4 的内存警告。有什么需要我检查的。我想知道也许我做错了什么。这是我尝试您的方式的代码。 UIImage *image= [UIImage imageWithCGImage:defaultRep.fullResolutionImage]; image2=[self generateThumbnailFromImage:image andOsize:newSize];
  • 我用仪器测量我的内存使用情况,它显示峰值约为 57MB。我认为这是内存警告的根本原因,还是其他原因?脏内存或与之相关的泄漏?我不知道脏内存的异常情况是什么...我的应用程序是多选图像以调整大小并上传到服务器。多选由 ALAssetlibrary 实现。当用户点击缩略图时,我会调整图像大小,然后有时可能会收到内存警告......我对这个问题感到沮丧一个月......感谢任何帮助。
  • 在您的情况下,警告不一定来自创建缩略图......可能会发生一些内存被其他对象分配并且一起使警告发生的情况。
  • 对不起,我不明白你的意思。如何防止内存警告?事实上,我只为用户可以看到的内容创建缩略图视图,可能是 28 个缩略图视图。但是,我真的觉得这与缩略图视图有关,因为我曾经使用图像选择器加载 8MP 图像,并且它从未显示内存警告。但在我目前的项目中,我使用assetlibrary,似乎更容易得到内存警告。所以,你的cmets是有价值的。顺便说一句,我在调整图像大小后收到内存警告。请告诉我更多细节。谢谢。
  • 我猜如果您在 iPad2 和 iPhone 4s 中经常收到内存警告,那么您应该检查您正在使用的资产库是否与您正在检查的 ios 兼容,我只能猜测可能是发生在这么多信息上。
【解决方案2】:

我发现当我使用 3rd 方 JPEG 解码库(libjpeg-turbo)在 2048x2048 UIImage 下对其进行解码和调整大小时,它减少了很多。(即使总内存也没有减少太多。)所以可能导致内存频繁发生通过创建大于 2Kx2K 的 UIImage。希望这会有所帮助。

【讨论】:

猜你喜欢
  • 2011-05-17
  • 2013-10-10
  • 2012-09-03
  • 2012-11-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-09
  • 1970-01-01
  • 2021-11-07
相关资源
最近更新 更多