Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何解决在视网膜显示设备中加载图像时占用大量内存空间的问题?_Ios_Objective C_Opengl Es_Memory Profiling - Fatal编程技术网

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

Ios 如何解决在视网膜显示设备中加载图像时占用大量内存空间的问题?,ios,objective-c,opengl-es,memory-profiling,Ios,Objective C,Opengl Es,Memory Profiling,我正在开发一个iPad paint应用程序,用户可以在其中绘制N幅图像,并有一个图库将绘制的图像导出到不同的社交网络等。这里的问题是,我收到了很多内存警告(最终导致崩溃)当我使用iPad视网膜设备时。我尝试分析并发现,与非视网膜设备相比,imageio_png_数据、VM:CoreAnimation、VM:CG光栅数据等项目占用了大量内存。我知道这与图像加载有关,因为我正在应用程序中加载png、JPG等图像文件格式 1.如何解决在视网膜显示设备中加载图像时占用大量内存空间的问题 2.如何使应用程

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

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

2.如何使应用程序避免对imageio_png_数据、VM:CoreAnimation、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的大小调整为UIImageViews大小;对于视网膜,将views大小乘以2。

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

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

如果情况并非如此,并且您实际上加载了太多的纹理,那么您需要考虑如何最小化纹理计数或其分辨率,这样您就达到了设备的功能,并且没有什么可以做的了。此外,使用纹理图集可能会对您有很大帮助

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