【问题标题】:Memory consumption spikes when resizing, rotating and cropping images on iPhone在 iPhone 上调整、旋转和裁剪图像时,内存消耗会激增
【发布时间】:2011-06-30 23:45:43
【问题描述】:

我有一个“ImageManipulator”类,可以在 iPhone 上对相机图像进行一些裁剪、调整大小和旋转。

目前,一切都按预期运行,但我不断收到一些巨大的内存消耗峰值,这有时会导致应用崩溃。

我已设法将问题隔离到我检查当前图像方向属性并将其相应地旋转到UIImageOrientationUp 的代码的一部分。然后我从位图上下文中获取图像并将其保存到磁盘。

这是我目前正在做的:

CGAffineTransform transform = CGAffineTransformIdentity;
// Check for orientation and set transform accordingly...
transform = CGAffineTransformTranslate(transform, self.size.width, 0);
transform = CGAffineTransformScale(transform, -1, 1);

// Create a bitmap context with the image that was passed so we can perform the rotation
CGContextRef ctx = CGBitmapContextCreate(NULL, self.size.width, self.size.height,
                                         CGImageGetBitsPerComponent(self.CGImage), 0,
                                         CGImageGetColorSpace(self.CGImage),
                                         CGImageGetBitmapInfo(self.CGImage));

// Rotate the context
CGContextConcatCTM(ctx, transform);

// Draw the image into the context
CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage);

// Grab the bitmap context and save it to the disk...

即使在尝试将图像缩小到大小的一半甚至 1/4 之后,我仍然看到尖峰,我想知道是否有其他/更有效的方法来完成上述旋转?

提前感谢您的回复。 罗格

【问题讨论】:

  • 图片有多大?我们遇到了类似的问题,所以我们首先将图像缩小到可接受的尺寸,然后应用旋转。
  • 您是否在冗长的操作中创建大型自动释放对象?
  • 内存峰值是因为CGBitmapContextCreate 必须分配一个缓冲区来保存图像数据,这大约是width * height * CGImageGetBitsPerComponent(self.CGImage) / 8 字节。如果CGContextDrawImage 需要在绘制之前加载或解压缩原始图像的图像数据,它也可能分配另一个类似大小的缓冲区。不过,我不知道有什么更有效的方法。

标签: iphone ios core-graphics cgcontext


【解决方案1】:

如果您要保存为 JPEG,我想另一种方法是按原样保存图像,然后通过操作 EXIF 元数据将旋转设置为您想要的任何值?参见例如this post。简单但可能有效,即使您必须将图像有效负载字节保存在内存中;)

【讨论】:

    【解决方案2】:

    你可以做的事情:

    1. 进一步缩小图像(您可能不想要)

    2. 记得在完成后立即发布所有内容

    3. 接受它

    我会选择选项 2 和 3。

    图像编辑非常耗费资源,因为它将整个原始未压缩图像数据加载到内存中进行处理。这是不可避免的,因为除了将完整的原始数据加载到内存中之外,绝对没有其他方法可以修改图像。除非应用程序收到内存警告,否则内存消耗峰值并不重要,在这种情况下,在崩溃之前迅速摆脱所有内容。但是,您很少会收到内存警告,因为我的应用程序会定期将单个 > 10 mb 的文件加载到内存中,即使在较旧的设备上,我也不会收到警告。所以你会没事的。

    【讨论】:

      【解决方案3】:
      • 您是否尝试过检查内存泄漏和分析分配?
      • 如果图像仍然太大,请尝试将图像分段而不是整体旋转。

      【讨论】:

        【解决方案4】:

        正如 Anomie 提到的,CGBitmapContextCreate 创建了一个上下文。我们应该使用

        来释放它
        CGContextRelease(ctx);
        

        如果您有任何其他使用 create 或 copy 创建的对象,则也应将其释放。如果是CFData,那么

        CFRelease(cfdata);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-10-23
          • 1970-01-01
          • 2015-02-18
          • 2020-02-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多