如何解决在视网膜显示设备中加载图像占用大量内存空间的问题



我正在开发一个iPad绘画应用程序,用户可以在其中绘制N个图像,并拥有一个画廊将绘制的图像导出到不同的社交网络等。这里的问题是,当我使用iPad视网膜设备时,我收到了很多内存警告(最终导致崩溃(。我尝试了分析,并确定imageio_png_data,VM:CoreAnimation,VM:CG光栅数据等项目与非视网膜设备中的相同数据相比占用了大量内存。我知道这与图像加载有关,因为我正在应用程序中加载PNG,JPG文件格式等图像。

1.如何解决在视网膜显示设备中加载图像占用大量内存的问题

2.如何使应用程序避免imageio_png_data,VM:核心动画,VM:CG栅格数据等术语的大量内存消耗。

3.我得到了一些信息,像PVR纹理这样的图像可用于解决图像的内存相关问题。我是否可以将其集成到本机iOS应用程序中。(我也在运行时保存图像,因为它是一个绘画应用程序。

如果此选项适合您,您可以压缩低质量的图像。

UIImage *image = [UIImage imageNamed:@"image.png"];
NSData *imageData = UIImageJPEGRepresentation(image, 0.2); // 0.2 - quality
UIImage *lowQualityImage=[UIImage imageWithData:data];

如果您有许多映像不将它们存储在数组中,请使用 NSCache。

您应该在 UIImage 类别中实现此方法:

- (UIImage *)resizedImage:(CGSize)newSize
                transform:(CGAffineTransform)transform
           drawTransposed:(BOOL)transpose
     interpolationQuality:(CGInterpolationQuality)quality {
    CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
    CGRect transposedRect = CGRectMake(0, 0, newRect.size.height, newRect.size.width);
    CGImageRef imageRef = self.CGImage;
    // Build a context that's the same dimensions as the new size
    CGContextRef bitmap = CGBitmapContextCreate(NULL,
                                                newRect.size.width,
                                                newRect.size.height,
                                                CGImageGetBitsPerComponent(imageRef),
                                                0,
                                                CGImageGetColorSpace(imageRef),
                                                CGImageGetBitmapInfo(imageRef));
    // Rotate and/or flip the image if required by its orientation
    CGContextConcatCTM(bitmap, transform);
    // Set the quality level to use when rescaling
    CGContextSetInterpolationQuality(bitmap, quality);
    // Draw into the context; this scales the image
    CGContextDrawImage(bitmap, transpose ? transposedRect : newRect, imageRef);
    // Get the resized image from the context and a UIImage
    CGImageRef newImageRef = CGBitmapContextCreateImage(bitmap);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
    // Clean up
    CGContextRelease(bitmap);
    CGImageRelease(newImageRef);
    return newImage;
}
并将您的UIImage调整为非视网膜的

UIImage视图大小,并将视网膜的视图大小乘以2。

使用视网膜 (x2( 图像时,您正在加载的图像占用的内存约为 4 倍,而 (x3( 图像占用的内存约为 (x3( 的 9 倍。使用 png 等格式时的数据需要解压缩、复制并发送到 GPU,在某些情况下,这会导致每个图像的内存中有 3 个图像数据副本,这显然是不好的。您的iPad仍然应该有足够的内存来加载更多纹理,然后您可以实时绘制。

从您告诉我们的内容来看,很难知道您的问题真正在哪里,但您应该确保的第一件事是加载图像时,您应该序列化操作。这意味着您应该加载 1 个纹理,确保所有图像数据都已从加载中清除(3 个副本中的 2 个(,然后开始加载下一个纹理。我不知道你用什么来加载纹理,但老式的"获取原始RGBA数据"应该在你的情况下是最好的。

如果不是这种情况,并且您实际上加载了太多纹理,那么您需要考虑如何最小化纹理数量或其分辨率,您达到了设备功能,并且您无能为力。使用纹理图集可能会对您有很大帮助。

在纹理加载和删除

方面,您可以考虑重用纹理,向其发送新数据,而不是删除和创建新纹理。对于图像数据本身,您可以在一些加载时间内加载图像(甚至可能是第一次运行应用程序(,然后将原始RGBA数据保存到新文件中。使用这种方法将显着减少纹理加载时间和内存占用,缺点是您将使用用户磁盘空间。

最新更新