【问题标题】:Add transparent space around a UIImage在 UIImage 周围添加透明空间
【发布时间】:2013-11-16 17:31:18
【问题描述】:

假设我们有一个 600X400 像素的图像,我们希望最终得到一个 1000x1000 像素的新图像,其中包含中心的初始图像和它周围的透明空间。如何在代码中实现这一点?

【问题讨论】:

  • 国际海事组织不应关闭。问题定义明确并且很有用。

标签: ios cocoa-touch uiimage


【解决方案1】:

在 Swift 中,您可以为 UIImage 编写一个扩展来绘制带有插图的图像。

Swift 3

import UIKit

extension UIImage {
    func imageWithInsets(insets: UIEdgeInsets) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(
            CGSize(width: self.size.width + insets.left + insets.right,
                   height: self.size.height + insets.top + insets.bottom), false, self.scale)
        let _ = UIGraphicsGetCurrentContext()
        let origin = CGPoint(x: insets.left, y: insets.top)
        self.draw(at: origin)
        let imageWithInsets = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return imageWithInsets
    }
}

老答案

import UIKit

extension UIImage {
    func imageWithInsets(insets: UIEdgeInsets) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(
            CGSizeMake(self.size.width + insets.left + insets.right,
                self.size.height + insets.top + insets.bottom), false, self.scale)
        let context = UIGraphicsGetCurrentContext()
        let origin = CGPoint(x: insets.left, y: insets.top)
        self.drawAtPoint(origin)
        let imageWithInsets = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return imageWithInsets
    }
}

【讨论】:

  • 知道为什么有时这可能会返回 nil 吗?
  • 参见developer.apple.com/reference/uikit/…:仅当基于位图的图形上下文是当前图形上下文时,才应调用此函数。如果当前上下文为 nil 或不是通过调用 UIGraphicsBeginImageContext(_:) 创建的,则此函数返回 nil。
  • @mixel 只是一个小建议:它应该是return imageWithInsets?.withRenderingMode(renderingMode) 以便也支持模板图像
【解决方案2】:

这是 Swift 4 中受 DrummerB 答案启发的解决方案:

import UIKit

extension UIImage {

    func addImagePadding(x: CGFloat, y: CGFloat) -> UIImage? {
        let width: CGFloat = size.width + x
        let height: CGFloat = size.height + y
        UIGraphicsBeginImageContextWithOptions(CGSize(width: width, height: height), false, 0)
        let origin: CGPoint = CGPoint(x: (width - size.width) / 2, y: (height - size.height) / 2)
        draw(at: origin)
        let imageWithPadding = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return imageWithPadding
    }
}

如何申请:

let image = UIImage(named: "your-image")!
let imageView = UIImageView(image: image.addImagePadding(x: 50, y: 50))
imageView.backgroundColor = UIColor.gray
view.addSubview(imageView)

特点:

  • 只需通过参数传递填充值
  • 彩色填充(通过将 UIGraphicsBeginImageContextWithOptions 不透明参数设置为 false)

【讨论】:

    【解决方案3】:

    您创建一个 1000x1000 的新图像上下文,在中间绘制旧图像,然后从上下文中获取新的 UIImage

    // Setup a new context with the correct size
    CGFloat width = 1000;
    CGFloat height = 1000;
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), NO, 0.0);        
    CGContextRef context = UIGraphicsGetCurrentContext();       
    UIGraphicsPushContext(context);                             
    
    // Now we can draw anything we want into this new context.
    CGPoint origin = CGPointMake((width - oldImage.size.width) / 2.0f,
                                (height - oldImage.size.height) / 2.0f);
    [oldImage drawAtPoint:origin];
    
    // Clean up and get the new image.
    UIGraphicsPopContext();                             
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    

    【讨论】:

    • 亲爱的鼓手 B!非常感谢您发布有效的解决方案。唯一的修正是替换 CGPoint origin = CGRectMake((width - oldImage.size.width) / 2.0f, (height - oldImage.size.height) / 2.0f); with CGPoint origin = CGPointMake((width - oldImage.size.width) / 2.0f, (height - oldImage.size.height) / 2.0f);
    • @DrummerB 你不希望UIGraphicsBeginImageContextWithOptions 中的opaque 参数为NO,因为他想要透明空间吗?
    【解决方案4】:

    在 UIImage 上创建一个类别并试试这个:

    + (UIImage *)imageWithInsets:(CGRect)insetRect image:(UIImage *)image {
        CGRect newRect = CGRectMake(0.0, 0.0, insetRect.origin.x+insetRect.size.width+image.size.width, insetRect.origin.y+insetRect.size.height+image.size.height);
        // Setup a new context with the correct size
        UIGraphicsBeginImageContextWithOptions(newRect.size, NO, 0.0);
        CGContextRef context = UIGraphicsGetCurrentContext();
        UIGraphicsPushContext(context);
    
        // Now we can draw anything we want into this new context.
        CGPoint origin = CGPointMake(insetRect.origin.x, insetRect.origin.y);
        [image drawAtPoint:origin];
    
        // Clean up and get the new image.
        UIGraphicsPopContext();
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return newImage;
    }
    

    【讨论】:

      【解决方案5】:

      通过更好的命名约定修复了 appsunited 的答案。为了不混淆它,函数是否正在变异:

      extension UIImage {
          func withPadding(_ padding: CGFloat) -> UIImage? {
              return withPadding(x: padding, y: padding)
          }
      
          func withPadding(x: CGFloat, y: CGFloat) -> UIImage? {
              let newWidth = size.width + 2 * x
              let newHeight = size.height + 2 * y
              let newSize = CGSize(width: newWidth, height: newHeight)
              UIGraphicsBeginImageContextWithOptions(newSize, false, 0)
              let origin = CGPoint(x: (newWidth - size.width) / 2, y: (newHeight - size.height) / 2)
              draw(at: origin)
              let imageWithPadding = UIGraphicsGetImageFromCurrentImageContext()
              UIGraphicsEndImageContext()
      
              return imageWithPadding
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2017-06-27
        • 2015-03-10
        • 1970-01-01
        • 2014-09-12
        • 2012-08-31
        • 2015-01-07
        • 2018-06-27
        • 1970-01-01
        • 2011-10-31
        相关资源
        最近更新 更多