调整 UIImage 的 canvas 大小并用颜色填充空白处?

Resize UIImage's canvas and fill the empty place with color?

简单来说,我想"revert"裁剪操作。在裁剪中,您选择一个矩形并将图像剪切到指定的矩形。在我的例子中,我需要做相反的事情——在图像周围添加空白 space 并用颜色填充它。注意 - 图片可能有透明背景,所以我不能只在另一张图片上绘制一张图片。

我已经拥有的所有输入数据(矩形和图像)。如何解决这个任务?

基本流程:

  1. 创建纯色 UIImage
  2. 获取 CGContext
  3. 使用 (Obj-C) CGContextClearRect(CGContextRef c, CGRect rect); 或 (Swift) .clear(_ rect: CGRect)
  4. 清除新 UIImage 中心的一个矩形
  5. 将原图绘制到新图"transparent rect"中

这是一个例子,使用 Swift:

func drawImageOnCanvas(_ useImage: UIImage, canvasSize: CGSize, canvasColor: UIColor ) -> UIImage {

    let rect = CGRect(origin: .zero, size: canvasSize)
    UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)

    // fill the entire image
    canvasColor.setFill()
    UIRectFill(rect)

    // calculate a Rect the size of the image to draw, centered in the canvas rect
    let centeredImageRect = CGRect(x: (canvasSize.width - useImage.size.width) / 2,
                                   y: (canvasSize.height - useImage.size.height) / 2,
                                   width: useImage.size.width,
                                   height: useImage.size.height)

    // get a drawing context
    let context = UIGraphicsGetCurrentContext();

    // "cut" a transparent rectanlge in the middle of the "canvas" image
    context?.clear(centeredImageRect)

    // draw the image into that rect
    useImage.draw(in: centeredImageRect)

    // get the new "image in the center of a canvas image"
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return image!

}

并这样称呼它:

    if let img = UIImage(named: "myimage") {

        let expandedSize = CGSize(width: img.size.width + 60, height: img.size.height + 60)

        let imageOnBlueCanvas = drawImageOnCanvas(img, canvasSize: expandedSize, canvasColor: .blue)

        let v = UIImageView(image: imageOnBlueCanvas)

        view.addSubview(v)

    }

非常好,DonMag,

此处与 UIImage 扩展相同,可以将图像定位在 canvas。

extension UIImage {
    enum Position {                                         // the position of the image in the canvas
        case top
        case bottom
        case left
        case right
        case middle
        case topLeft
        case topRight
        case bottomLeft
        case bottomRight
    }
    
    func drawOnCanvas(withCanvasSize canvasSize: CGSize,
                      andCanvasColor canvasColor: UIColor,
                      atPosition position: Position) -> UIImage {
        let rect = CGRect(origin: .zero, size: canvasSize)
        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
        canvasColor.setFill()                               // fill the entire image
        UIRectFill(rect)
        
        var x = 0.0                                         // the position of the image in the canvas
        var y = 0.0
        switch position {                                   // look at the position specified
        case .top:
            x = (canvasSize.width - self.size.width) / 2    // position horizontally in the middle
        case .bottom:
            x = (canvasSize.width - self.size.width) / 2    // position horizontally in the middle
            y = canvasSize.height - self.size.height        // and vertically at the bottom
        case .left:
            y = (canvasSize.height - self.size.height) / 2  // position vertically in the middle
        case .right:
            x = canvasSize.width - self.size.width          // position horizontally at the right
            y = (canvasSize.height - self.size.height) / 2  // and vertically in the middle
        case .middle:
            x = (canvasSize.width - self.size.width) / 2    // position horizontally in the middle
            y = (canvasSize.height - self.size.height) / 2  // and vertically in the middle
        case .topLeft:
            x = 0.0                                         // just dummy
        case .topRight:
            x = canvasSize.width - self.size.width          // position horizontally at the right
        case .bottomLeft:
            y = canvasSize.height - self.size.height        // position vertically at the bottom
        case .bottomRight:
            x = canvasSize.width - self.size.width          // position horizontally at the right
            y = canvasSize.height - self.size.height        // and vertically at the bottom
        }
        // calculate a Rect the size of the image to draw, centered in the canvas rect
        let positionedImageRect = CGRect(x: x,              // position the image in the canvas
                                         y: y,
                                         width: self.size.width,
                                         height: self.size.height)
        let context = UIGraphicsGetCurrentContext()         // get a drawing context
        // "cut" a transparent rectanlge in the middle of the "canvas" image
        context?.clear(positionedImageRect)
        self.draw(in: positionedImageRect)                  // draw the image into that rect
        let image = UIGraphicsGetImageFromCurrentImageContext() // get the new "image in the canvas image"
        UIGraphicsEndImageContext()
        return image!                                       // and return it
    }
}

使用情况:

let imageOnBlueCanvas = img.drawOnCanvas(withCanvasSize: expandedSize, andCanvasColor: .blue, atPosition: .middle)