#ios #swift #uiimage #cgimage #ciimage
#iOS #swift #uiimage #cgimage #ciimage
Вопрос:
Есть ли возможность реплицировать func masking(_ mask: CGImage) -> CGImage?
из Core Graphics с помощью CoreImage и одного из CIFilter
? Я пытался CIBlendWithMask
и CIBlendWithAlphaMask
безуспешно. Самое главное, что мне нужно сохранить альфа-канал, поэтому я хочу, чтобы изображение было замаскировано таким образом, что если маска черная -> показать изображение, если маска белая -> прозрачная. Мой код маскировки:
extension UIImage {
func masked(by mask: UIImage) -> UIImage {
guard let maskRef = mask.cgImage,
let selfRef = cgImage,
let dataProvider = maskRef.dataProvider,
let mask = CGImage(
maskWidth: maskRef.width,
height: maskRef.height,
bitsPerComponent: maskRef.bitsPerComponent,
bitsPerPixel: maskRef.bitsPerPixel,
bytesPerRow: maskRef.bytesPerRow,
provider: dataProvider,
decode: nil,
shouldInterpolate: false),
let masked = selfRef.masking(mask) else {
fatalError("couldnt create mask!")
}
let maskedImage = UIImage(cgImage: masked)
return maskedImage
}
}
Ответ №1:
Я нашел решение. Ключ в том, чтобы использовать изображение в формате оттенков серого, rgb и другие не будут работать. Шаг изменения размера можно удалить, если изображение и maks имеют одинаковый размер. Выполнимо как расширение, может быть выполнено и как подкласс CIImage. Наслаждайтесь 🙂
Конечно, его можно изменить как расширение на UIImage
, CIImage
, CIFilter
, как вам нравится.
extension CGImage {
func masked(by cgMask: CGImage) -> CIImage {
let selfCI = CIImage(cgImage: self)
let maskCI = CIImage(cgImage: cgMask)
let maskFilter = CIFilter(name: "CIMaskToAlpha")
maskFilter?.setValue(maskCI, forKey: "inputImage")
let scaleFilter = CIFilter(name: "CILanczosScaleTransform")
scaleFilter?.setValue(maskFilter?.outputImage, forKey: "inputImage")
scaleFilter?.setValue(selfCI.extent.height / maskCI.extent.height, forKey: "inputScale")
let filter: CIFilter! = CIFilter(name: "CIBlendWithAlphaMask")
filter.setValue(selfCI, forKey: "inputBackgroundImage")
let maskOutput = scaleFilter?.outputImage
filter.setValue(maskOutput, forKey: "inputMaskImage")
let outputImage = filter.outputImage!
return outputImage
}
}
Ответ №2:
Вам нужно создать свой собственный пользовательский фильтр. Учебные пособия:
Raywenderlich.com Учебное пособие
Это не тривиально, но это окупается, когда вы узнаете, как это сделать 🙂
Комментарии:
1. О черт. Действительно. Я пытался использовать clear ciimage в качестве входного изображения и использовать изображение для фильтрации в качестве фона, нулевых результатов. Возможно, моя маска неверна. Может быть, маска должна составлять один байт на пиксель, изображение в оттенках серого для маски?
2. Я упростил CIImage 🙂