ByteNoteByteNote
二值化按宽度走会踩到填充
字

字节笔记本

2026年10月7日 · 约 2 分钟读完

二值化按宽度走会踩到填充

API中转
¥120

示例导入的是 UIKit。三种静态方法都收一张 UIImage,没有 cgImage 就返回空。

灰度只保留层次

灰度方法建立设备灰色彩色空间,位图信息是没有透明通道,每分量 8 位,bytesPerRow 传 0。把原图画进这块上下文,再 makeImage 包回 UIImage。bytesPerRow 为 0 时,行距由系统按对齐选择,可以大于宽度。这里只画一次,不按字节改像素,所以对齐不影响结果。效果是保留深浅的灰度,不是只有黑白两色。

滤镜方法用 CIPhotoEffectMono。输入键是 kCIInputImageKey。输出范围用 outputImage.extent,每次调用都新建一个 CIContext。这是相机式的黑白,仍然有灰阶。和第一种不是同一条实现。

阈值循环假设行距等于宽度

二值化先做同样的灰度上下文,默认阈值 0.5。然后把 data 绑成 UInt8,循环次数是宽度乘高度。像素大于阈值写成 255,否则写成 0。示例调用把阈值改成 0.6。

循环把内存当成宽度紧挨着排。bytesPerRow 为 0 时,一行的实际字节数常常大于宽度,多出来的是对齐填充。按宽度乘高度去写,会把填充算进下一行的像素,后面的点就错位。要按行处理,步长必须用上下文真正的 bytesPerRow,每行只改宽度那么多个字节。

循环次数用了宽度乘高度

三种方法的差别就在这里。灰度和滤镜不改单个字节。只有二值化在写指针。文档扫描要的是非黑即白,才用阈值。要层次就停在前两种。

没有 cgImage 的图,三种都返回空。命名图片 sample.jpg 只是调用示例。

行距大于宽度时像素会错位

滤镜每次新建上下文。连续处理很多张时,这份创建成本会重复。对话没有做复用。

阈值用大于,等于阈值的像素变成 0。0.5 和 0.6 的分界不同。示例两处数字都要看,默认参数是 0.5。

UIKit 的 UIImage 是这段的类型。它不是前面那篇 AppKit 拖放视图。

相关文章

分享: