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

在Swift的Metalkit库中能否获取或计算图像像素的x、y索引?

结论

你当前Metal代码里通过[[thread_position_in_grid]]拿到的id变量,就是你需要的对应像素的X、Y坐标,和你原CPU遍历逻辑里的x、y完全等价,可以直接使用。


前提:网格尺寸和纹理尺寸对齐

你只需要在Swift侧配置Metal管线调用时,保证计算网格的尺寸和输入/输出纹理的宽高完全匹配即可,示例配置代码如下:

// 假设你已经把CGImage转成了Metal纹理,宽高分别为textureWidth、textureHeight
let gridSize = MTLSize(width: textureWidth, height: textureHeight, depth: 1)
// 线程组大小根据GPU核心配置,一般用16x16或者32x32即可
let threadGroupSize = MTLSize(width: 16, height: 16, depth: 1)
// 调用compute encoder派发任务
computeEncoder.dispatchThreads(gridSize, threadsPerThreadgroup: threadGroupSize)

如果你的设备需要兼容iOS 11以下、macOS 10.13以下系统,不支持dispatchThreads接口,可以用下面的兼容写法计算对齐后的线程组数量:

let threadGroupCount = MTLSize(
    width: (textureWidth + threadGroupSize.width - 1) / threadGroupSize.width,
    height: (textureHeight + threadGroupSize.height - 1) / threadGroupSize.height,
    depth: 1
)
computeEncoder.dispatchThreadgroups(threadGroupCount, threadsPerThreadgroup: threadGroupSize)

这种情况下kernel内要先判断id是否超出纹理尺寸,避免越界访问,补全后的kernel代码参考:

kernel void clearPixel (
    texture2d<float, access::read> inTexture [[texture(0)]],
    texture2d<float, access::write> outTexture [[texture(1)]],
    uint2 id [[thread_position_in_grid]]
) {
    // 先判断坐标是否在纹理范围内,避免越界
    if (id.x >= inTexture.get_width() || id.y >= inTexture.get_height()) {
        return;
    }
    // 直接用id.x、id.y和目标坐标判断即可,和原CPU逻辑完全一致
    if (id.x == 20 && id.y == 300) {
        // 写入透明色,RGBA格式下透明值为[0,0,0,0]
        outTexture.write(float4(0, 0, 0, 0), id);
    } else {
        // 其余像素直接复制原图内容
        outTexture.write(inTexture.read(id), id);
    }
}

坐标一致性说明

Metal纹理的默认原点为左上角,和你原CGImage遍历逻辑中y从0到cgImage.height的坐标体系完全对齐,不需要额外做坐标转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 03:12:02