ios – 使用CGImageCreate调整图像大小以减少内存使用量

有时图像非常大(从互联网上下载),所以我需要调整它们的大小但不想导致内存问题,这意味着我不想将所有图像数据加载到内存并在内存中调整大小.

我正在调查调整图像大小的方法,监控他们的记忆用法.具体来说,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);

但实际上,如果图像很大,您应该使用下载任务,以便整个图像永远不会在内存中,但会在到达时保存到磁盘.

点赞