您能否仅将较大的磁盘映像的较小矩形部分加载到内存中?

Posted

技术标签:

【中文标题】您能否仅将较大的磁盘映像的较小矩形部分加载到内存中?【英文标题】:Can you load only a smaller rectangular portion of a larger on-disk image into memory? 【发布时间】:2012-05-15 16:18:27 【问题描述】:

ios 和大多数移动设备上,由于内存限制,您可以加载的图像大小受到限制。是否可以在磁盘上有一个大图像(比如 5,000 像素 x 5,000 像素)但只将该图像中的一个较小的矩形(比如 100x100)读取到内存中进行显示?

换句话说,如果您只想查看其中的一小部分,是否需要将整个图像加载到内存中?如果可以只加载较小的部分,我们该怎么做?

这样一来,就可以像 spritesheets 那样为重复的内容节省大量空间。请务必注意,总体目标是最小化文件大小,因此应使用 jpeg 或 png 或其他某种压缩方式压缩大图像。我怀疑视频格式是这样的,因为您永远不会将整个视频加载到内存中。

【问题讨论】:

你在用 5k x 5k 的图像做什么?另外,你的文件是什么格式的? 【参考方案1】:

虽然我没有使用这些技术,但您可能会发现以下 Apple 示例很有用:

LargeImageDownsizing Sample

【讨论】:

【参考方案2】:

您可以像这样使用映射的NSData 做一些事情:

UIImage *pixelDataForRect(NSString *fileName, const CGRect pixelRect)

    // get the pixels from that image
    uint32_t width = pixelRect.size.width;
    uint32_t height = pixelRect.size.height;

    // create the context
    UIGraphicsBeginImageContext(CGSizeMake(width, height));
    CGContextRef bitMapContext = UIGraphicsGetCurrentContext();

    CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, height);
    CGContextConcatCTM(bitMapContext, flipVertical);

    // render the image (assume PNG compression)
    CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef) [NSData dataWithContentsOfMappedFile:fileName]);
    CGImageRef image = CGImageCreateWithPNGDataProvider(provider, NULL, YES, kCGRenderingIntentDefault);
    CGDataProviderRelease(provider);

    uint32_t imageWidth = CGImageGetWidth(image);
    uint32_t imageHeight = CGImageGetHeight(image);

    CGRect drawRect = CGRectMake(-pixelRect.origin.x, -((imageHeight - pixelRect.origin.y) - height), imageWidth, imageHeight);
    CGContextDrawImage(bitMapContext, drawRect, image);

    CGImageRelease(image);

    UIImage *retImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return retImage;

【讨论】:

【参考方案3】:

最好的办法是使用带有 CATiledLayer 的 UIScrollView。

查看 WWDC 2010 的“使用滚动视图设计应用程序”演示文稿,了解如何执行此操作:

https://developer.apple.com/videos/wwdc/2010/

这个想法是把你的大图像切成小块,然后使用 UIScrollView 为你的用户提供图像的可滚动视图,仅根据图像的位置加载那些必要的部分滚动视图。这是使用 CATiledLayer 完成的。

【讨论】:

以上是关于您能否仅将较大的磁盘映像的较小矩形部分加载到内存中?的主要内容,如果未能解决你的问题,请参考以下文章

自定义排序数组 - 较大值之间的较小值

在 Wcf REST 中,返回请求较少的较大模型还是返回请求较多的较小模型更好

SQL取两列的较小值或者较大值

SQL取两列的较小值或者较大值

使用部分映射更新 pandas DataFrame 的列

从没有 BIOS 服务的 INT 13 的软盘加载 OS 映像