在iPhone上缩放和裁剪巨大的图像

时间:2021-11-19 21:20:47

For the last few weeks I've been tearing my hair out trying to get a tiling mechanism working on an iPhone. I need to scale and crop images of about 150mb so that they can be saved as tiles that will be requested by a scroll view, allowing the user to see the image in high resolution.

在过去的几个星期里,我一直在绞尽脑汁地想弄个能在iPhone上工作的贴条机制。我需要缩放和裁剪大约150mb的图像,这样它们就可以保存为滚动视图请求的块,允许用户以高分辨率查看图像。

The problem is that these images are really pushing the bounds of what an iPhone can handle. It seems quite easy to scale these huge images down to 1000 or so across and do that tiling, but for large zoom levels I need to scale it mid-way, say 4000 across and that's too big. So I hit upon the idea of making medium sized blocks from the full sized image and tiling each of those and the medium zoom.

问题是,这些图像确实在推动iPhone能够处理的范围。很容易把这些巨大的图像缩小到1000左右,这样做,但是对于大的缩放级别,我需要把它缩放到中间,比如4000,这太大了。所以我想到了用全尺寸的图像制作中等大小的方块,然后把每一个都铺上瓷砖,然后用中变焦。

By creating an autoreleasepool around the inner loops, and draining it after each cycle I can mostly keep the memory under control but sometimes, and to me it seems random, memory is getting leaked, or at least not drained. I'm doing all this on a secondary thread and when it gets back to the first function in that thread I release the thread's own autoreleasepool and only then do the last memory artifacts get cleared. It doesn't seem to bother the simulator but the iPhone is much less forgiving and it crashes before it can complete the whole tiling process. The cropping code I am using is from Hive05

通过在内部循环周围创建一个autoreleasepool,并在每个循环之后耗尽它,我基本上可以控制内存,但有时,对我来说,它似乎是随机的,内存被泄露了,或者至少没有耗尽。我在一个次要线程上执行所有这些操作,当它返回到线程的第一个函数时,我释放线程自己的autoreleasepool,然后才会清除最后的内存工件。这似乎并没有影响到模拟器,但iPhone的宽容程度要低得多,而且在完成整个tiling过程之前就会崩溃。我使用的裁剪代码来自Hive05

http://www.hive05.com/2008/11/crop-an-image-using-the-iphone-sdk/

http://www.hive05.com/2008/11/crop-an-image-using-the-iphone-sdk/

Has anyone else had to deal with such massive images before? Is pre-generating tiles the best way to go? Any suggestions on why some loops would increase the memory and some not, or how to force every auto-released thing to clear on the inner pool instead of waiting for the outer pool?

以前有谁必须处理如此巨大的图像吗?预生成瓦片是最好的方法吗?对于为什么有些循环会增加内存而有些不会,或者如何迫使每个自动释放的东西清除内部池而不是等待外部池,有什么建议吗?

Thanks for reading this far.

感谢您一直以来的阅读。

for got to add, these images are TIFs, so perhaps a direct reading of the bitmap info would be better than scaling and cropping the entire thing

对于get to add,这些图像是TIFs,所以直接读取位图信息可能比缩放和裁剪整个东西要好

2 个解决方案

#1


0  

First of all, I have serious doubts that an 150 MB image would fit in the device's memory, even if we're talking about a 3GS. That one has about 128 MB available memory for 3rd party apps maximum. See the device console messages and look for memory warnings, I guess you'll see that before crashing, the app emits them when trying to load your image. Reading the bitmap info in chunks would seem more sensible, as you'll be managing smaller sections at a time. I don't think Cocoa has a random-access file API, so you'll have to resort to a C function.

首先,我非常怀疑一个150 MB的图像是否能放进设备的内存中,即使我们说的是3GS。它有大约128mb的可用内存用于第三方应用程序。查看设备控制台消息并查找内存警告,我猜您将在崩溃之前看到,应用程序在尝试加载映像时发出警告。将位图信息按块读取似乎更明智,因为您将同时管理更小的部分。我认为Cocoa没有随机访问的文件API,所以你必须使用C函数。

#2


0  

I've managed to write the loops that cycle through tiles of 1024x1024 and my iPhone 3G is able to finish the processing. It takes over 30 minutes though so it isn't great but that's what you get for working with 150mb TIF on a cellphone.

我成功地编写了循环遍历1024x1024块的循环,我的iPhone 3G能够完成处理。虽然它需要30分钟,所以它不是很好,但这就是你在手机上使用150mb TIF所得到的。

To keep the memory usage low I had to drain the AutoReleasepools after each iteration. Apple Tech Support pointed out that since the iPhone is a reference-counted environment rather than a garbage collected environment it is better to create a new AutoReleasePool at the start of each inner loop and drain it at the end of each loop than to create it before any loops start, drain it many times and then release it after the loops are done. Until I made that change my app would crash an iPhone but run fine on the simulator.

为了保持低内存使用率,我必须在每次迭代之后耗尽自动维护池。苹果技术支持指出,由于iPhone是一个采用引用计数的环境,而不是一个垃圾收集环境最好是创建一个新的AutoReleasePool开始时每个内循环和排泄它每次循环结束时比任何循环开始之前,创建它流失很多次循环完成后,然后释放它。在我做出改变之前,我的应用程序会让iPhone崩溃,但在模拟器上运行良好。

#1


0  

First of all, I have serious doubts that an 150 MB image would fit in the device's memory, even if we're talking about a 3GS. That one has about 128 MB available memory for 3rd party apps maximum. See the device console messages and look for memory warnings, I guess you'll see that before crashing, the app emits them when trying to load your image. Reading the bitmap info in chunks would seem more sensible, as you'll be managing smaller sections at a time. I don't think Cocoa has a random-access file API, so you'll have to resort to a C function.

首先,我非常怀疑一个150 MB的图像是否能放进设备的内存中,即使我们说的是3GS。它有大约128mb的可用内存用于第三方应用程序。查看设备控制台消息并查找内存警告,我猜您将在崩溃之前看到,应用程序在尝试加载映像时发出警告。将位图信息按块读取似乎更明智,因为您将同时管理更小的部分。我认为Cocoa没有随机访问的文件API,所以你必须使用C函数。

#2


0  

I've managed to write the loops that cycle through tiles of 1024x1024 and my iPhone 3G is able to finish the processing. It takes over 30 minutes though so it isn't great but that's what you get for working with 150mb TIF on a cellphone.

我成功地编写了循环遍历1024x1024块的循环,我的iPhone 3G能够完成处理。虽然它需要30分钟,所以它不是很好,但这就是你在手机上使用150mb TIF所得到的。

To keep the memory usage low I had to drain the AutoReleasepools after each iteration. Apple Tech Support pointed out that since the iPhone is a reference-counted environment rather than a garbage collected environment it is better to create a new AutoReleasePool at the start of each inner loop and drain it at the end of each loop than to create it before any loops start, drain it many times and then release it after the loops are done. Until I made that change my app would crash an iPhone but run fine on the simulator.

为了保持低内存使用率,我必须在每次迭代之后耗尽自动维护池。苹果技术支持指出,由于iPhone是一个采用引用计数的环境,而不是一个垃圾收集环境最好是创建一个新的AutoReleasePool开始时每个内循环和排泄它每次循环结束时比任何循环开始之前,创建它流失很多次循环完成后,然后释放它。在我做出改变之前,我的应用程序会让iPhone崩溃,但在模拟器上运行良好。