CG raster data too large for one image

时间:2017-04-24 17:37:11

标签: ios objective-c uiimage core-graphics

I was trying to rotate an UIImage of 2448x3264 taken with the camera. When I do, the memory spikes 120Mb approximately, for more or less 3/4 seconds and then returns to its normal state. The problem is that, in devices with less memory(for instance, ipod touch), the app crashes. Even if it doesn't, I don't think it should use that much memory for one image. Iphone 5 is also lagged when this happens.

According to a comment in this answer, the size in bytes of the decompressed memory after using UIGraphicsGetCurrentContext() should be width * height * CGImageGetBitsPerComponent(image.CGImage) / 8 bytes, so the image should occupy 8Mb, not 120.

Any idea why this happens and how to fix it?

Here's the UIImage caterogy method to return a rotated image:

- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees {
    CGFloat radian = (CGFloat) (degrees * (M_PI/ 180.0f));
    CGSize rotatedSize = [self rotatedImageSize:degrees];

    // Create the bitmap context
    UIGraphicsBeginImageContextWithOptions(rotatedSize, NO, 0);
    CGContextRef bitmap = UIGraphicsGetCurrentContext();

    CGPoint contextCenter = CGPointMake(rotatedSize.width/2.0f, 
rotatedSize.height/2.0f);
    CGContextTranslateCTM(bitmap, contextCenter.x, contextCenter.y);

    //   // Rotate the image context
    CGContextRotateCTM(bitmap, radian);
    // Now, draw the rotated/scaled image into the context
    [self drawInRect:CGRectMake(-self.size.width/2.0f, -
self.size.height/2.0f, self.size.width, self.size.height)];

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

Here's proof from instruments that the raster data is what's causing the peak in memory, just when the rotate method is executed:

Instruments proof

1 个答案:

答案 0 :(得分:0)

几条评论:

  • 2448x3264x(比如说4个字节/像素)约为30兆字节。
  • 不要旋转它。如果它在屏幕上,您可以使用视图的转换属性。如果它进入文件并且旋转是8个exif方向之一,则写入元数据,说明哪个方向已启动。同样,如果它来自文件,请使用Image I / O并要求CGImageSourceRef生成一个定向缩略图,其大小需要将其放在屏幕上。 (提示使用kCGImageSourceThumbnailMaxPixelSize和kCGImageSourceCreateThumbnailWithTransform。)对于任意角度,您可以使用CoreImage过滤器,该过滤器将旋转图像并缩减采样到屏幕所需的大小(在GPU上)。同样,您可以使用vImage在CPU上执行相同的操作(提示vImageAffineWarpCG_ARGB8888)。 vImage非常快,它会比核心图形提供更好的重采样。等等......如果它疼,就不要这样做。
  • 在花时间从角度转换为旋转矩阵之前,您应该暂停一下。例如,如果你的角度是90度,你想要的矩阵就是[0 1 -1 0 0 0],你的重采样代码会比你计算的近似结果更快乐。旋转矩阵是[cos(t)sin(t)-sin(t)cos(t)0 0]。客户很可能已经直接传入余弦和正弦。