我正在使用Rob Mayoff在对this SO question的回答中提供的代码,作为创建向UIImage(不一定是字符串)添加浮雕功能的起点。我正在尝试不同的实现,但遇到了麻烦。在我的代码中(见下文),我有两个不同版本的函数,该函数为字符串生成掩码。 mask1(Rob's)和mask2(mine)。他们似乎都正常工作。但是,当我将蒙版传递给求反函数时,Rob的蒙版正确取反,而我的蒙皮被翻转了。
This SO question似乎提供了解释,但我无法完全解释,因为它仅发生在其中一张蒙版图像上。
模拟器屏幕截图包含四个图像视图。从顶部开始:1)Rob的面具,2)Rob的面具的底片,3)我的面具,4)我的面具的底片。
我已将项目放在github
有人可以帮我了解发生了什么事吗?
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var imageView1: UIImageView!
@IBOutlet weak var imageView2: UIImageView!
@IBOutlet weak var imageView3: UIImageView!
@IBOutlet weak var imageView4: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
let text = "Verticon"
let font = UIFont(name: "Helvetica", size: 100)!
let size = imageView1.bounds.size
let maskA = mask1(from: text, drawnWith: font, andSize: size)
imageView1.image = maskA
let negativeA = negative(of: maskA)
imageView2.image = negativeA
let maskB = mask2(from: text, drawnWith: font, andSize: size)
imageView3.image = maskB
let negativeB = negative(of: maskB)
imageView4.image = negativeB
}
}
extension ViewController {
// Draw the specified string using the provided attributes and return the resultant image (which has only an alpha channel, no color information).
func mask1(from string: String, drawnWith font: UIFont, andSize size: CGSize) -> UIImage {
let scale = UIScreen.main.scale
let colorSpace = CGColorSpaceCreateDeviceGray()
let bitmapInfo = CGImageAlphaInfo.alphaOnly.rawValue
guard let context = CGContext(data: nil, width: Int(size.width * scale), height: Int(size.height * scale), bitsPerComponent: 8, bytesPerRow: Int(size.width * scale), space: colorSpace, bitmapInfo: bitmapInfo) else { fatalError("mask1() - cannot create a graphics context") }
context.scaleBy(x: scale, y: scale)
UIGraphicsPushContext(context)
let rect = CGRect(origin: CGPoint.zero, size: size)
let attributes: [NSAttributedStringKey : Any] = [.font : font]
string.draw(in: rect, withAttributes: attributes)
UIGraphicsPopContext()
guard let cgImage = context.makeImage() else { fatalError("mask1() - could not get image from context.") }
return UIImage(cgImage: cgImage, scale: scale, orientation: .downMirrored)
}
// Draw the specified string using the provided attributes and return the resultant image.
func mask2(from string: String, drawnWith font: UIFont, andSize size: CGSize) -> UIImage {
let renderer = UIGraphicsImageRenderer(size: size)
return renderer.image { ctx in
let rect = CGRect(origin: CGPoint.zero, size: size)
let attributes: [NSAttributedStringKey : Any] = [.font : font, .foregroundColor : UIColor.white]
string.draw(in: rect, withAttributes: attributes)
}
}
// Return a black rectangle wherein the area corresponding to the specified image has been cleared (made transparent).
func negative(of: UIImage) -> UIImage {
UIGraphicsBeginImageContextWithOptions(of.size, false, of.scale)
let rect = CGRect(origin: .zero, size: of.size)
UIColor.black.setFill()
UIRectFill(rect)
guard let cgImage = of.cgImage else { fatalError("negative() - could not obtain CGImage.") }
guard let context = UIGraphicsGetCurrentContext() else { fatalError("negative() - could not obtain CGContext.") }
context.clip(to: rect, mask: cgImage)
context.clear(rect)
guard let negative = UIGraphicsGetImageFromCurrentImageContext() else { fatalError("invert() could not obtain negative.") }
UIGraphicsEndImageContext();
return negative;
}
}