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

Swift macOS中CGContext无法绘制圆点问题求助

解决CGImage上无法绘制圆点(GCRect)的问题

我看了你的代码,发现几个关键问题导致圆点无法正确显示,下面一步步帮你修正:

1. 未绘制原始图像到上下文

你注释掉了context.draw(image, in: faceRect),这会导致最终生成的CGImage只有你尝试绘制的圆点(即使圆点正确也看不到原始图像),首先要把这行代码恢复,确保原始图像被绘制到上下文里。

2. 椭圆边界矩形计算错误

你当前计算boundingRect的width和height的方式完全错误,这样会生成一个超大的椭圆而不是直径5的圆点。正确的做法是:圆点的中心应该对应point.x * image.width和point.y * image.height,所以需要将矩形的x和y偏移-diameter/2,然后width和height都设为diameter,这样才能得到一个中心在目标点、直径为5的正圆。

3. 未填充椭圆路径

你只调用了context.addEllipse(in: boundingRect)添加路径,但没有调用context.fillPath()来填充颜色,所以就算路径正确也不会显示任何内容。

4. 坐标系翻转问题

CGContext默认的Y轴是向下的,而图像的坐标系通常是Y轴向上的,所以需要翻转上下文的Y轴,否则圆点的Y坐标会颠倒。


修正后的完整代码

public func drawFaceDots(onImage image: CGImage) -> CGImage {
    let faceRect = CGRect(x: 0, y: 0, width: image.width, height: image.height)
    let diameter: CGFloat = 5
    
    // 创建上下文,增加失败处理
    guard let context = CGContext(data: nil,
                                  width: image.width,
                                  height: image.height,
                                  bitsPerComponent: 8,
                                  bytesPerRow: 4 * image.width,
                                  space: CGColorSpaceCreateDeviceRGB(),
                                  bitmapInfo: CGImageAlphaInfo.premultipliedFirst.rawValue) else {
        return image
    }
    
    // 翻转Y轴,匹配图像坐标系
    context.translateBy(x: 0, y: CGFloat(image.height))
    context.scaleBy(x: 1.0, y: -1.0)
    
    // 绘制原始图像到上下文
    context.draw(image, in: faceRect)
    
    // 设置填充颜色(统一放在循环外,避免重复设置)
    context.setFillColor(NSColor.green.cgColor)
    
    guard let originalFace = self.orignalFace else {
        return context.makeImage() ?? image
    }
    
    for point in originalFace {
        print("Point(\(point.x);\(point.y))")
        // 计算圆点的中心坐标
        let centerX = point.x * CGFloat(image.width)
        let centerY = point.y * CGFloat(image.height)
        // 计算圆点的边界矩形:中心偏移半径,宽高为直径
        let boundingRect = CGRect(x: centerX - diameter/2,
                                  y: centerY - diameter/2,
                                  width: diameter,
                                  height: diameter)
        print("BoundingRect : \(boundingRect)")
        // 添加椭圆路径并填充
        context.addEllipse(in: boundingRect)
        context.fillPath()
    }
    
    return context.makeImage() ?? image
}

额外说明

  • 我添加了guard let来处理orignalFace为空和上下文创建失败的情况,让代码更健壮;
  • 翻转坐标系的代码translateBy和scaleBy是关键,确保圆点位置和你预期的一致;
  • 每次添加椭圆后调用fillPath(),确保颜色被填充到路径中;
  • 统一将填充颜色设置放在循环外,避免重复设置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:10:37