有时图像非常大(从互联网上下载),所以我需要调整它们的大小但不想导致内存问题,这意味着我不想将所有图像数据加载到内存并在内存中调整大小.
我正在调查调整图像大小的方法,监控他们的记忆用法.具体来说,CGContextDrawImage,CGImageSourceCreateThumbnailAtIndex和CGImageCreate与CGDataProviderRef.
现在我在使用CGImageCreate和CGDataProviderRef时遇到了一些问题,我的代码是这样的:
//This method read the data from filePath, resize the image and write the resized data to the destPath
- (void)resizeImageFileUsingCGImageCreate:(NSString*)filePath toDestPath:(NSString*)destPath {
CGFloat factor = 0.2;
CGSize originalSize = [self sizeOfImageAtURL:[[NSURL alloc] initFileURLWithPath:filePath]];
CGSize destSize = CGSizeMake((NSUInteger)(originalSize.width * factor), (NSUInteger)(originalSize.height * factor));
UIImage *srcImage = [UIImage imageWithContentsOfFile:filePath];
CGImageRef srcImgRef = srcImage.CGImage;
NSData *data = [NSData dataWithContentsOfFile:filePath];
CFDataRef cfData = (__bridge_retained CFDataRef)data;
CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(cfData);
CFRelease(cfData);
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(srcImgRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGImageRef imageRef = CGImageCreate(destSize.width, destSize.height, 8, 32, 4 * destSize.width, colorSpace, bitmapInfo, dataProvider, NULL, NO, 0);
CGDataProviderRelease(dataProvider);
CGColorSpaceRelease(colorSpace);
UIImage *image = nil;
if (imageRef != NULL) {
image = [[UIImage alloc] initWithCGImage:imageRef];
CGImageRelease(imageRef);
//Why UIImageJPEGRepresentation(image, 0.5) returns nil?
[UIImageJPEGRepresentation(image, 0.5) writeToFile:destPath atomically:YES];
}
}
在代码的最后一行,UIImageJPEGRepresentation(image,0.5)总是返回nil,这让我很奇怪.你能帮我指出使用CGImageCreate和CGDataProviderRef调整图像大小的正确方法吗?非常感谢!
最佳答案 我没有直接回答您的问题,而是向您展示我认为更好的方法:使用ImageIO框架.
#import <ImageIO/ImageIO.h>
以下是如何从磁盘加载缩小尺寸版本的图像(imageSource是NSURL;必须事先将scale,maxw和maxh设置为您想要的比例和最大尺寸):
CGImageSourceRef src =
CGImageSourceCreateWithURL((__bridge CFURLRef)imageSource, nil);
NSDictionary* d = @{
(id)kCGImageSourceShouldAllowFloat: (id)kCFBooleanTrue,
(id)kCGImageSourceCreateThumbnailWithTransform: (id)kCFBooleanTrue,
(id)kCGImageSourceCreateThumbnailFromImageAlways: (id)kCFBooleanTrue,
(id)kCGImageSourceThumbnailMaxPixelSize: @((int)(maxw > maxh ? maxw : maxh))
};
CGImageRef imref =
CGImageSourceCreateThumbnailAtIndex(src, 0, (__bridge CFDictionaryRef)d);
if (NULL != src)
CFRelease(src);
UIImage* im =
[UIImage imageWithCGImage:imref scale:scale orientation:UIImageOrientationUp];
if (NULL != imref)
CFRelease(imref);
关于这段代码的好处是我们永远不会在内存中保存大图像;永远不会加载.我们最终得到了一个更小的UIImage,我们准备在我们的界面中使用它.
如果您拥有来自Internet的NSData并且尚未将其保存到磁盘,那么要创建图像源,请使用以下命令:
src = CGImageSourceCreateWithData((__bridge CFDataRef)imageSource, nil);
但实际上,如果图像很大,您应该使用下载任务,以便整个图像永远不会在内存中,但会在到达时保存到磁盘.