我有几张大小约1.5 MB的大图片。我使用UIViewContentModeScaleFit在UIImageView中显示它们。
UIImageViews的帧大小只有150 * 150。
我的问题是
我知道如果我为全屏显示大图像,内存将会大幅增加。
但如果他们在小型UIImageView中,他们还会花费内存吗?
由于
答案 0 :(得分:3)
UIImage
和UIImageView
是不同的东西。每个UIImageView
都知道显示其关联的UIImage
的大小。 UIImage
没有关于如何展示自身或如何用于展示的概念,因此仅仅改变UIImageView
的大小的行为对UIImage
没有影响。因此它对总内存使用量没有影响。
您可能想要做的是使用Core Graphics获取UIImage
并将其生成150x150版本作为新UIImage
,然后将其推送到UIImageView
。
要执行比例,代码类似于以下内容(按我输入的方式编写,因此未经过彻底检查)应该完成这项工作:
#include <math.h>
- (UIImage *)scaledImageForImage:(UIImage *)srcImage toSize:(CGSize)maxSize
{
// pick the target dimensions, as though applying
// UIViewContentModeScaleAspectFit; seed some values first
CGSize sizeOfImage = [srcImage size];
CGSize targetSize; // to store the output size
// logic here: we're going to scale so as to apply some multiplier
// to both the width and height of the input image. That multiplier
// is either going to make the source width fill the output width or
// it's going to make the source height fill the output height. Of the
// two possibilities, we want the smaller one, since the larger will
// make the other axis too large
if(maxSize.width / sizeOfImage.width < maxSize.height / sizeOfImage.height)
{
// we'll letter box then; scaling width to fill width, since
// that's the smaller scale of the two possibilities
targetSize.width = maxSize.width;
// height is the original height adjusted proportionally
// to match the proportional adjustment in width
targetSize.height =
(maxSize.width / sizeOfImage.width) * sizeOfImage.height;
}
else
{
// basically the same as the above, except that we pillar box
targetSize.height = maxSize.height;
targetSize.width =
(maxSize.height / sizeOfImage.height) * sizeOfImage.width;
}
// images can be integral sizes only, so round up
// the target size and width, then construct a target
// rect that centres the output image within that size;
// this all ensures sub-pixel accuracy
CGRect targetRect;
// store the original target size and round up the original
targetRect.size = targetSize;
targetSize.width = ceilf(targetSize.width);
targetSize.height = ceilf(targetSize.height);
// work out how to centre the source image within the integral-sized
// output image
targetRect.origin.x = (targetSize.width - targetRect.size.height) * 0.5f;
targetRect.origin.y = (targetSize.height - targetRect.size.width) * 0.5f;
// now create a CGContext to draw to, draw the image to it suitably
// scaled and positioned, and turn the thing into a UIImage
// get a suitable CoreGraphics context to draw to, in RGBA;
// I'm assuming iOS 4 or later here, to save some manual memory
// management.
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(
NULL,
targetSize.width, targetSize.height,
8, targetSize.width * 4,
colourSpace,
kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colourSpace);
// clear the context, since it may currently contain anything.
CGContextClearRect(context,
CGRectMake(0.0f, 0.0f, targetSize.width, targetSize.height));
// draw the given image to the newly created context
CGContextDrawImage(context, targetRect, [srcImage CGImage]);
// get an image from the CG context, wrapping it as a UIImage
CGImageRef cgImage = CGBitmapContextCreateImage(context);
UIImage *returnImage = [UIImage imageWithCGImage:cgImage];
// clean up
CGContextRelease(context);
CGImageRelease(cgImage);
return returnImage;
}
显然,我通过大量评论看起来很复杂,但它实际上只有23行。
答案 1 :(得分:1)
它们在帧缓冲存储器(即保持像素用于显示的存储器)方面不会花费太多,但是将未缩放的图像保持在存储器中仍将产生相当大的成本。如果1.5MB是压缩大小。这可能是高(iOS使用大约4个字节*宽度*每个图像的高度来存储未压缩的UIImage
s)。当你的应用程序进入后台时,这些图像与内核将执行的自动内存管理交互不良 - 后备存储在内存压力发生时被释放,但后备图像不是。
解决这个问题的最佳方法(如果你应该自己调整大小,存储较小的版本,并释放大版本)是使用VM Tracker通过Instruments运行你的应用程序。如果存储图像的区域过多,您将能够诊断它们,并选择适当的解决方案。您可能希望在iOS内存管理上查看WWDC 2011会话,其中详细介绍了图像内存使用情况,包括使用Instruments查找问题。
在优化之前,像往常一样,配置文件(或者,正如Apple可能会说的,仪器)!
答案 2 :(得分:1)
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>
+ (UIImage *)resizeImage:(UIImage *)image toResolution:(int)resolution {
NSData *imageData = UIImagePNGRepresentation(image);
CGImageSourceRef src = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
CFDictionaryRef options = (__bridge CFDictionaryRef) @{
(id) kCGImageSourceCreateThumbnailWithTransform : @YES,
(id) kCGImageSourceCreateThumbnailFromImageAlways : @YES,
(id) kCGImageSourceThumbnailMaxPixelSize : @(resolution)
};
CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, options);
CFRelease(src);
UIImage *img = [[UIImage alloc]initWithCGImage:thumbnail];
return img;
}
答案 3 :(得分:0)
是的。你应该创建缩小版本的图像,将它们缓存到某个地方的磁盘,在图像视图中使用小版本,如果可以的话,卸载大版本。