You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过组合CIFilters在图像编辑APP中显示高光与阴影裁剪?

用CIFilter组合实现高光与阴影裁剪的可行思路

嘿,我刚好在iOS/macOS图像编辑场景里折腾过类似需求,确实没有现成的单一CIFilter能一步到位实现高光与阴影裁剪,但通过几个滤镜的组合完全能搞定!下面是我验证过的两种可行方案,你可以根据自己的需求选:


方案一:蒙版分离法(精准控制,保留色彩)

这种方法会先提取高光/阴影区域的蒙版,再把超出阈值的区域替换成固定亮度值,能精准保留原图像的色彩细节:

步骤1:转线性颜色空间(可选但更准确)

CIFilter的很多颜色操作在线性空间下计算更精准,先把sRGB图像转成线性空间:

let linearImage = originalImage.applyingFilter("CISRGBToneCurveToLinear")

步骤2:生成高光/阴影蒙版

通过颜色矩阵提取亮度通道,再用阈值滤镜生成蒙版:

// 生成高光蒙版:亮度>0.8的区域为白色(需要裁剪的部分)
let highlightMask = linearImage
    .applyingFilter("CIColorMatrix", parameters: [
        "inputRVector": CIVector(x: 0.2126, y: 0.7152, z: 0.0722, w: 0),
        "inputGVector": CIVector(x: 0.2126, y: 0.7152, z: 0.0722, w: 0),
        "inputBVector": CIVector(x: 0.2126, y: 0.7152, z: 0.0722, w: 0),
        "inputAVector": CIVector(x: 0, y: 0, z: 0, w: 1)
    ])
    .applyingFilter("CIThreshold", parameters: ["inputThreshold": 0.8])

// 生成阴影蒙版:亮度<0.2的区域为白色(需要裁剪的部分)
let shadowMask = linearImage
    .applyingFilter("CIColorMatrix", parameters: [
        "inputRVector": CIVector(x: 0.2126, y: 0.7152, z: 0.0722, w: 0),
        "inputGVector": CIVector(x: 0.2126, y: 0.7152, z: 0.0722, w: 0),
        "inputBVector": CIVector(x: 0.2126, y: 0.7152, z: 0.0722, w: 0),
        "inputAVector": CIVector(x: 0, y: 0, z: 0, w: 1)
    ])
    .applyingFilter("CIThreshold", parameters: ["inputThreshold": 0.2])
    .applyingFilter("CIColorInvert") // 反转后阴影区域为白色

步骤3:裁剪高光与阴影

用蒙版混合滤镜,把需要裁剪的区域替换成固定亮度:

// 裁剪高光:将高光区域替换为线性空间下的0.8亮度
let clippedHighlights = linearImage.applyingFilter("CIBlendWithMask", parameters: [
    "inputBackgroundImage": CIImage(color: CIColor(red: 0.8, green: 0.8, blue: 0.8)),
    "inputMaskImage": highlightMask
])

// 裁剪阴影:将阴影区域替换为线性空间下的0.2亮度
let clippedImage = clippedHighlights.applyingFilter("CIBlendWithMask", parameters: [
    "inputBackgroundImage": CIImage(color: CIColor(red: 0.2, green: 0.2, blue: 0.2)),
    "inputMaskImage": shadowMask
])

步骤4:转回sRGB颜色空间

最后把线性图像转回到显示用的sRGB空间:

let finalImage = clippedImage.applyingFilter("CILinearToSRGBToneCurve")

方案二:自定义色调曲线法(简洁高效)

如果不需要极致精准的蒙版控制,直接用CIToneCurve自定义曲线,把高光和阴影的亮度范围截断,步骤更简单:

let toneCurveFilter = CIFilter(name: "CIToneCurve")!
toneCurveFilter.setValue(originalImage, forKey: kCIInputImageKey)

// 自定义曲线:亮度<0.2的部分固定为0.2,>0.8的部分固定为0.8,中间线性过渡
toneCurveFilter.setValue(CIVector(x: 0, y: 0.2), forKey: "inputPoint0")
toneCurveFilter.setValue(CIVector(x: 1/3, y: 0.2 + (0.8-0.2)*(1/3)), forKey: "inputPoint1")
toneCurveFilter.setValue(CIVector(x: 2/3, y: 0.2 + (0.8-0.2)*(2/3)), forKey: "inputPoint2")
toneCurveFilter.setValue(CIVector(x: 1, y: 0.8), forKey: "inputPoint3")

let finalImage = toneCurveFilter.outputImage!

注意事项

  • 阈值参数(比如0.2、0.8)可以根据你的需求灵活调整,数值越接近0/1,裁剪的范围越小
  • 如果你需要保留原图像的色彩质感,优先选蒙版分离法
  • 可以把多个滤镜组合成CIFilterGroup,提升渲染性能

内容的提问来源于stack exchange,提问作者Gizmodo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:40:49