我正在开发一个应用程序,用户可能会尝试加载非常大的图像。这些图像首先在表格视图中显示为缩略图。我的原始代码会在大图像上崩溃,因此我将其重写为首先将图像直接下载到磁盘。
是否有一种已知方法可以在磁盘上调整图像大小而不通过UIImage
将其完全加载到内存中?我目前正在尝试使用UIImage
上的类别详细调整here,但我的应用在尝试缩放非常大的图片时崩溃(例如,this - 警告,巨大的形象)。
答案 0 :(得分:49)
你应该看看ImageIO.framework中的CGImageSource,但它只能在iOS 4.0之后使用。
快速举例:
-(UIImage*)resizeImageToMaxSize:(CGFloat)max path:(NSString*)path
{
CGImageSourceRef imageSource = CGImageSourceCreateWithURL((CFURLRef)[NSURL fileURLWithPath:path], NULL);
if (!imageSource)
return nil;
CFDictionaryRef options = (CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailWithTransform,
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailFromImageIfAbsent,
(id)@(max),
(id)kCGImageSourceThumbnailMaxPixelSize,
nil];
CGImageRef imgRef = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options);
UIImage* scaled = [UIImage imageWithCGImage:imgRef];
CGImageRelease(imgRef);
CFRelease(imageSource);
return scaled;
}
答案 1 :(得分:1)
根据本次会议iOS Memory Deep Dive,我们最好使用new Map({
target: 'map',
layers: [
new TileLayer({
source: new XYZ({
url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png'
})
})
],
view: new View({
center: [0, 0],
zoom: 2
})
});
来缩小图像尺寸。
使用ImageIO
缩小图像的缺点。
使用UIImage
ImageIO可以读取图像大小和元数据信息,而不会弄脏内存。
ImageIO只能以调整大小的图像为代价来调整图像的大小。
关于内存中的图像
ImageIO
始终使用UIGraphicsBeginImageContextWithOptions
渲染格式,每个像素使用4个字节。SRGB
3个阶段。load -> decode -> render
的大小和调整大小很昂贵对于下图,如果使用UIImage
我们只需要590KB即可加载图像,而我们需要
UIGraphicsBeginImageContextWithOptions
= 10MB(解码时)
在iOS 10中引入的2048 pixels x 1536 pixels x 4 bytes per pixel
会自动选择iOS12中的最佳图形格式。这意味着,如果不需要SRGB,可以将UIGraphicsImageRenderer
替换为UIGraphicsBeginImageContextWithOptions
,从而节省75%的内存。
这是我有关iOS images in memory
的文章UIGraphicsImageRenderer
或
func resize(url: NSURL, maxPixelSize: Int) -> CGImage? {
let imgSource = CGImageSourceCreateWithURL(url, nil)
guard let imageSource = imgSource else {
return nil
}
var scaledImage: CGImage?
let options: [NSString: Any] = [
// The maximum width and height in pixels of a thumbnail.
kCGImageSourceThumbnailMaxPixelSize: maxPixelSize,
kCGImageSourceCreateThumbnailFromImageAlways: true,
// Should include kCGImageSourceCreateThumbnailWithTransform: true in the options dictionary. Otherwise, the image result will appear rotated when an image is taken from camera in the portrait orientation.
kCGImageSourceCreateThumbnailWithTransform: true
]
scaledImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options as CFDictionary)
return scaledImage
}
let filePath = Bundle.main.path(forResource:"large_leaves_70mp", ofType: "jpg")
let url = NSURL(fileURLWithPath: filePath ?? "")
let image = resize(url: url, maxPixelSize: 600)