CGImageCreateWithImageInRect()返回nil

时间:2016-02-28 00:08:55

标签: ios swift optional cgimage

我试图将图像裁剪成正方形,但是一旦我尝试使用CGImageCreateWithImageInRect()进行裁剪,此线就会崩溃。我设置断点并确保传递给此函数的参数不是nil。

我对编程和Swift相当陌生,但已经四处寻找并找不到解决问题的方法。

失败原因:

  

致命错误:在解包可选值时意外发现nil

func cropImageToSquare(imageData: NSData) -> NSData {

    let image = UIImage(data: imageData)
    let contextImage : UIImage = UIImage(CGImage: image!.CGImage!)
    let contextSize: CGSize = contextImage.size

    let imageDimension: CGFloat = contextSize.height
    let posY : CGFloat = (contextSize.height + (contextSize.width - contextSize.height)/2)
    let rect: CGRect = CGRectMake(0, posY, imageDimension, imageDimension)

    // error on line below: fatal error: unexpectedly found nil while unwrapping an Optional value
    let imageRef: CGImageRef = CGImageCreateWithImageInRect(contextImage.CGImage, rect)!
    let croppedImage : UIImage = UIImage(CGImage: imageRef, scale: 1.0, orientation: image!.imageOrientation)

    let croppedImageData = UIImageJPEGRepresentation(croppedImage, 1.0)

    return croppedImageData!

}

1 个答案:

答案 0 :(得分:0)

您的代码使用了很多强制解包! s。我建议避免这种情况 - 编译器正在尝试帮助您编写不会崩溃的代码。使用与?if let / guard let的可选链接。

该特定行上的!隐藏了CGImageCreateWithImageInRect可能返回nil的问题。 The documentation解释说,当rect未在图像边界内正确时,会发生这种情况。您的代码适用于纵向图像,但不适用于横向图像。

此外,AVFoundation提供了一个方便的功能,它可以自动找到你要使用的正确矩形,称为AVMakeRectWithAspectRatioInsideRect。无需手动进行计算: - )

以下是我的建议:

import AVFoundation

extension UIImage
{
    func croppedToSquare() -> UIImage
    {
        guard let cgImage = self.CGImage else { return self }

        // Note: self.size depends on self.imageOrientation, so we use CGImageGetWidth/Height here.
        let boundingRect = CGRect(
            x: 0, y: 0,
            width: CGImageGetWidth(cgImage),
            height: CGImageGetHeight(cgImage))

        // Crop to square (1:1 aspect ratio) and round the resulting rectangle to integer coordinates.
        var cropRect = AVMakeRectWithAspectRatioInsideRect(CGSize(width: 1, height: 1), boundingRect)
        cropRect.origin.x = ceil(cropRect.origin.x)
        cropRect.origin.y = ceil(cropRect.origin.y)
        cropRect.size.width = floor(cropRect.size.width)
        cropRect.size.height = floor(cropRect.size.height)

        guard let croppedImage = CGImageCreateWithImageInRect(cgImage, cropRect) else {
            assertionFailure("cropRect \(cropRect) was not inside \(boundingRect)")
            return self
        }

        return UIImage(CGImage: croppedImage, scale: self.scale, orientation: self.imageOrientation)
    }
}

// then:
let croppedImage = myUIImage.croppedToSquare()