14

我正在开发一个自定义控件。要求之一是画线。虽然这可行,但我注意到我的 1 像素宽的线条看起来并不像 1 像素宽的线条 - 我知道,它们不是真正的像素,但你知道我的意思。它们看起来更像是两三个像素宽。当我用 1 像素虚线和 2 像素间隙绘制虚线时,这一点变得非常明显。1 像素的虚线实际上看起来像细线而不是点。

我已经阅读了 Cocoa Drawing 文档,虽然 Apple 提到了 setLineWidth 方法,但将线宽更改为小于 1.0 的值只会使线条看起来更模糊而不是更细。

所以,我怀疑还有其他东西影响了我的线条的外观。

有任何想法吗?

4

4 回答 4

25

贝塞尔路径以它们的路径为中心绘制,因此如果您沿 X 坐标绘制 1 像素宽的路径,则该线实际上是沿 Y 坐标绘制 { -0.5, 0.5 } 解决方案通常是将坐标偏移 0.5 以便该线未在子像素边界中绘制。您应该能够将边界框移动 0.5 以获得更清晰的绘图行为。

于 2011-11-04T22:57:29.480 回答
19

弗朗西斯·麦格鲁已经给出了正确的答案,但是因为我曾经做过一次关于这个的演讲,所以我想我会添加一些图片。

这里的问题是 Quartz 中的坐标位于像素之间的交叉点。这在填充矩形时很好,因为位于坐标内的每个像素都会被填充。但是线条在技术上(数学上!)是不可见的。要绘制它们,Quartz 必须实际绘制一个具有给定线宽的矩形。这个矩形以坐标为中心:

指定整数坐标时告诉 Quartz 绘制的矩形

所以当你让 Quartz 用整数坐标描边一个矩形时,它就有了只能画出整个像素的问题。但是在这里你看到我们有半个像素。所以它的作用是平均颜色。对于 50% 黑色(线条颜色)和 50% 白色(背景)线条,它只是将每个像素绘制为灰色:

在像素之间绘制时平均一半像素

这就是你褪色的图纸的来源。修复现在很明显:不要在像素之间绘制,您可以通过将点移动半个像素来实现这一点,因此您的坐标以所需像素为中心:

坐标向右下方偏移 0.5

现在当然只是抵消可能不是你想要的。因为如果您将填充的变体与描边的变体进行比较,则描边在右下角大一个像素。如果您要剪裁到矩形,这将切断右下角:

偏移描边和非偏移填充矩形之间的比较

由于人们通常希望矩形在指定的矩形内描边,因此您通常所做的就是向center偏移 0.5 ,因此右下角实际上向上移动了一个像素。或者,许多绘图应用程序从中心偏移 0.5 ,以避免边框和填充之间的重叠(当您使用透明度进行绘图时,这看起来很奇怪)。

请注意,这只适用于 1x 屏幕。2x Retina 屏幕实际上表现出这个问题的方式不同,因为下面的每个像素实际上都是由 4 个 Retina 像素绘制的,这意味着它们实际上可以绘制半个像素。但是,如果您想要一条 0.5pt 的尖线,您仍然会遇到同样的问题。此外,由于 Apple 将来可能会推出其他 Retina 屏幕,例如每个像素由 9 个 Retina 像素 (3x) 组成,或者其他什么,你真的不应该依赖这个。相反,现在有 API 调用将矩形转换为“支持对齐”,无论您是运行 1x、2x 还是虚构的 3x,它都会为您执行此操作。

PS - 因为我把这一切都写完了,我把它放在我的网站上:http: //orangejuiceliberationfront.com/are-your-rectangles-blurry-pale-and-have-rounded-corners /我将在此处更新和修改此描述并添加更多图像。

于 2014-03-08T10:11:21.513 回答
9

答案是(埋在)Apple Docs 中:

"为避免在绘制单点宽的水平或垂直线时出现抗锯齿,如果该线的宽度为奇数像素,则必须将该位置偏移 0.5 个点到整数位置的任一侧"

隐藏在iOS 绘图和打印指南中:iOS 绘图概念,尽管在当前的标准 (OS X) Cocoa 绘图指南中找不到具体内容。

至于调用文档setDefaultLineWidth:的效果还指出:

" 0 的宽度被解释为可以在特定设备上渲染的最细线。实际渲染的线宽可能与指定的宽度相差多达 2 个设备像素,具体取决于线相对于_

于 2013-03-26T08:08:41.203 回答
6

我发现一些信息表明这是由抗锯齿引起的。暂时关闭抗锯齿很容易:

[[NSGraphicsContext currentContext] setShouldAntialias: NO];

这给出了清晰的 1 像素线。画完再开机。

我尝试了 Francis McGrew 建议的解决方案,将 x 坐标偏移 0.5,但这对我的线条外观没有任何影响。

编辑:更具体地说,我分别更改了 x 和 y 坐标以及 0.5 的偏移量。

编辑 2:我一定做错了什么,因为用 0.5 的偏移量更改坐标实际上确实有效。最终结果比通过关闭抗锯齿获得的结果要好,所以我会让 Francis MsGrew 的答案成为公认的答案。

于 2011-11-05T09:08:41.993 回答