CGImageCreateWithImageInRect() 返回零

CGImageCreateWithImageInRect() returning nil

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

我对编程还很陌生,Swift,但我四处搜索并没有找到解决我的问题的方法。

失败原因:

fatal error: unexpectedly found nil while unwrapping an Optional value

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!

}

您的代码使用了很多 ! 的强制展开。我建议避免这种情况——编译器试图帮助您编写不会崩溃的代码。使用带有 ?if let / guard let 的可选链接。

该特定行上的 ! 隐藏了 CGImageCreateWithImageInRect 可能 return 为零的问题。 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()