如何通过ImageSharp的BinaryThresholdProcessor实现下阈值透明背景?
解决ImageSharp中BinaryThreshold白色背景转透明的问题
嘿,刚好我对ImageSharp的这个处理器有点了解,你观察到BinaryThresholdProcessor有上下阈值颜色属性没错,但默认这些属性是internal的,没法直接外部访问。不过有几种靠谱的方法能实现你的需求,我给你拆解一下:
方法1:自定义处理器重写逻辑(最灵活)
直接继承BinaryThresholdProcessor,重写它的帧处理方法,在阈值判断的时候直接把原本要设为下阈值白色的像素改成透明。这样能从根源上解决问题,不用额外后处理。
示例代码如下:
public class TransparentBinaryThresholdProcessor : BinaryThresholdProcessor { public TransparentBinaryThresholdProcessor(float threshold) : base(threshold) { } protected override void OnFrameApply<TPixel>(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) { // 先调用基类的阈值处理逻辑,生成黑白图像 base.OnFrameApply(source, sourceRectangle, configuration); // 定义透明像素 var transparentPixel = TPixel.FromRgba32(Color.Transparent); // 获取基类的下阈值颜色(同一程序集可直接访问;跨程序集的话可以用反射,或者直接用Color.White) var lowerThresholdColor = base.LowerThresholdColor; // 遍历所有像素,替换下阈值颜色为透明 for (int y = sourceRectangle.Top; y < sourceRectangle.Bottom; y++) { for (int x = sourceRectangle.Left; x < sourceRectangle.Right; x++) { var currentPixel = source[x, y]; if (currentPixel.Equals(lowerThresholdColor)) { source[x, y] = transparentPixel; } } } } }
如果是跨程序集访问LowerThresholdColor,可以用反射获取这个内部属性,或者干脆直接在代码里指定Color.White(毕竟默认下阈值就是白色),这样更稳妥。
方法2:后处理替换颜色(最简单)
如果不想折腾自定义处理器,直接在应用BinaryThreshold之后遍历图像像素,把白色换成透明就行。这种方法快速上手,不需要了解处理器内部逻辑:
using var image = Image.Load("your-input-image.png"); // 先应用阈值效果 image.Mutate(ctx => ctx.BinaryThreshold(0.5f)); // 这里的阈值根据你的需求调整 // 遍历图像帧,替换白色为透明 var frame = image.Frames[0]; for (int y = 0; y < frame.Height; y++) { for (int x = 0; x < frame.Width; x++) { var rgba = frame[x, y].ToRgba32(); if (rgba == Color.White) { frame[x, y] = Color.Transparent.ToPixel<Rgba32>(); } } } image.Save("output-with-transparent-bg.png");
方法3:反射访问内部属性(不推荐,仅作备选)
如果你一定要直接访问BinaryThresholdProcessor的内部上下阈值属性,可以用反射来获取,但这种方法依赖库的内部实现,一旦ImageSharp更新修改了属性名称或访问修饰符,代码就会失效。示例代码大概是这样:
var thresholdProcessor = new BinaryThresholdProcessor(0.5f); // 获取内部的LowerThresholdColor属性 var lowerColorProp = typeof(BinaryThresholdProcessor) .GetProperty("LowerThresholdColor", BindingFlags.Instance | BindingFlags.NonPublic); if (lowerColorProp != null) { var lowerColor = (Color)lowerColorProp.GetValue(thresholdProcessor); // 之后用这个颜色去图像里替换即可,逻辑和方法2类似 }
总结推荐
优先选方法1或方法2:方法1适合需要多次复用这个逻辑的场景,方法2适合快速实现需求。方法3尽量别用,兼容性太差。
内容的提问来源于stack exchange,提问作者lateAtNight
相关产品推荐
相关产品推荐

