如何使用 CGContext 获取像素的 RGB 值?

2023-12-02

我正在尝试通过更改像素来编辑图像。

我有以下代码:

    let imageRect = CGRectMake(0, 0, self.image.image!.size.width, self.image.image!.size.height)

    UIGraphicsBeginImageContext(self.image.image!.size)
    let context = UIGraphicsGetCurrentContext()

    CGContextSaveGState(context)
    CGContextDrawImage(context, imageRect, self.image.image!.CGImage)

    for x in 0...Int(self.image.image!.size.width) {
        for y in 0...Int(self.image.image!.size.height) {
            var red = 0
            if y % 2 == 0 {
                red = 255
            }

            CGContextSetRGBFillColor(context, CGFloat(red/255), 0.5, 0.5, 1)
            CGContextFillRect(context, CGRectMake(CGFloat(x), CGFloat(y), 1, 1))
        }
    }
    CGContextRestoreGState(context)
    self.image.image = UIGraphicsGetImageFromCurrentImageContext()

我循环遍历所有像素并更改每个像素的值,然后将其转换回图像。我想要做的是以某种方式获取当前像素的值(在 y-for-循环中)并对该数据执行某些操作。我没有在互联网上找到任何关于这个特定问题的信息。


在幕后,UIGraphicsBeginImageContext创建一个CGBitmapContext。您可以使用以下方式访问上下文的像素存储CGBitmapContextGetData。这种方法的问题在于UIGraphicsBeginImageContext函数选择用于存储像素数据的字节顺序和颜色空间。这些选择(特别是字节顺序)可能会在未来版本的 iOS 中(甚至在不同的设备上)发生变化。

因此,让我们直接创建上下文CGBitmapContextCreate,这样我们就可以确定字节顺序和颜色空间。

在我的游乐场中,我添加了一个名为的测试图像[email protected].

import XCPlayground
import UIKit

let image = UIImage(named: "pic.jpeg")!
XCPCaptureValue("image", value: image)

以下是我们创建位图上下文的方式,考虑到图像比例(您在问题中没有这样做):

let rowCount = Int(image.size.height * image.scale)
let columnCount = Int(image.size.width * image.scale)
let stride = 64 * ((columnCount * 4 + 63) / 64)
let context = CGBitmapContextCreate(nil, columnCount, rowCount, 8, stride,
    CGColorSpaceCreateDeviceRGB(),
    CGBitmapInfo.ByteOrder32Little.rawValue |
    CGImageAlphaInfo.PremultipliedLast.rawValue)

接下来,我们调整坐标系以匹配UIGraphicsBeginImageContextWithOptions就可以了,这样我们就可以正确、轻松地绘制图像:

CGContextTranslateCTM(context, 0, CGFloat(rowCount))
CGContextScaleCTM(context, image.scale, -image.scale)

UIGraphicsPushContext(context!)
image.drawAtPoint(CGPointZero)
UIGraphicsPopContext()

注意UIImage.drawAtPoint takes image.orientation考虑到。CGContextDrawImage才不是。

现在让我们从上下文中获取指向原始像素数据的指针。如果我们定义一个结构来访问每个像素的各个组件,则代码会更清晰:

struct Pixel {
    var a: UInt8
    var b: UInt8
    var g: UInt8
    var r: UInt8
}

let pixels = UnsafeMutablePointer<Pixel>(CGBitmapContextGetData(context))

请注意,顺序Pixel成员被定义为匹配我在中设置的特定位bitmapInfo论证CGBitmapContextCreate.

现在我们可以循环像素。请注意,我们使用rowCount and columnCount,如上计算,访问所有像素,无论图像比例如何:

for y in 0 ..< rowCount {
    if y % 2 == 0 {
        for x in 0 ..< columnCount {
            let pixel = pixels.advancedBy(y * stride / sizeof(Pixel.self) + x)
            pixel.memory.r = 255
        }
    }
}

最后,我们从上下文中得到一个新图像:

let newImage = UIImage(CGImage: CGBitmapContextCreateImage(context)!, scale: image.scale, orientation: UIImageOrientation.Up)

XCPCaptureValue("newImage", value: newImage)

结果,在我的游乐场的时间表中:

timeline screenshot

最后,请注意,如果您的图像很大,则逐像素浏览可能会很慢。如果您能找到一种使用 Core Image 或 GPUImage 执行图像操作的方法,速度会快很多。如果做不到这一点,使用 Objective-C 并手动对其进行矢量化(使用 NEON 内在函数)可能会带来很大的提升。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 CGContext 获取像素的 RGB 值? 的相关文章

随机推荐

  • 上传带有 Angular 材质和 Angular JS 的文件

    对于代码 我从中得到了灵感 https codepen io alexandergaziev pen JdVQQm 所以 对于 HTML 我这样做了 div class file input div div class file input
  • 使用C在eclipse中多重定义主要错误

    我正在尝试使用 Eclipse 中的 C 项目生成两个 exe 客户端和服务器 两者都有主要功能 因为他们是不同的前任 两者都使用通用的 confutils c 文件 如何解决主要问题的多重定义 我知道我们不能在一个项目中有两个电源 我的
  • 源中包含 < 和 > 的 XSLT 转换

    我有一个以下格式的输入 XML
  • 在 R 中重新编码多个变量

    我想在 R 中一次重新编码多个变量 这些变量位于更大的数据框中 以下是一些示例数据 z lt data frame A c 1 2 300 444 555 B c 555 444 300 2 1 C c 1 2 300 444 555 D
  • Angular UI Router - 如何在切换视图时保留视图

    我是 Angular 和 UI Router 的新手 Plunk http plnkr co edit 1wfyrGryfGG5RtXozPFY p preview Setup我有三个顶级应用程序导航按钮 主页 项目 帮助 他们使用 Ang
  • R.java 文件未创建

    我的 Android 应用程序中有 R java 文件 但我不知道 它是如何删除的 要再次创建它 我清理我的项目 并通过单击 构建项目 重建我的项目 我不知道是什么问题 它不会再次被创建 一般来说 每当我构建项目时它都会自动创建 如果您在更
  • firebase获取每个子项的子项的数据

    大家好 我是 firebase 的超级新手 我需要一些帮助 首先 我正在做的是一份清单 例如 刻度表包含一个项目列表 其中包含刻度日志 因此我设计的数据如下 清单 ticksheets JbN5ol2jGRtAOZ9ovrO auto ge
  • noscript 标签,如果未启用,我需要提供替代 html

    如果用户浏览器上未启用 JavaScript 是否可以用 HTML 替换 javascript 我知道我可以使用
  • 当以 C++03 为目标时,使用 std::basic_string 作为连续缓冲区是否合理?

    我知道在 C 03 中 从技术上讲std basic string模板不需要有连续的内存 然而 我很好奇现代编译器有多少实现实际上利用了这种自由 例如 如果有人想使用basic string要接收某些 C API 的结果 如下面的示例 分配
  • 是否可以从具有超时的输入流中读取?

    具体来说 问题是编写一个这样的方法 int maybeRead InputStream in long timeout 如果数据在 超时 毫秒内可用 则返回值与 in read 相同 否则返回 2 在该方法返回之前 任何生成的线程都必须退出
  • 您如何简单地解释类型转发?

    我正在准备 MCTS 70 536 阅读后this文章 我不确定我是否理解类型转发的概念 我发现文章中给出的步骤更加令人困惑 如果我复制要转发的类型的源代码并重新编译它 该怎么办 旧的 dll 和客户端会发生什么 类型转发允许您在程序集之间
  • 如何在Python中将日转换为年和月?

    如何在Python中将日转换为年 月和日 例如 如果某人已经 5 538 天了 我怎样才能通过这样的年月日来显示这一点 15岁2个月又1天 这是为了获取用户的输入 print Please enter your birthday bd ye
  • UICollectionView - 水平排列单元格

    所以基本上我的问题是我的集合视图单元格是从上到下排序的 而不是从左到右排序的 This is what it looks like 1 4 7 2 5 8 3 6 9 This is what i want 1 2 3 4 5 6 7 8
  • 需要在角度2中插入Script标签

    我已经做了一些阅读和搜索 几乎所有我发现的内容都表明脚本标签不能包含在 Angular 2 的模板中 我们会像您一样有意从模板中删除标签 不应该使用它们来按需加载代码 https github com angular angular iss
  • 特定元素是否存在事件

    是否有任何事件可以知道原始 javascript 中特定元素何时 开始存在 例如我有 div class parent div class child div div 我想在 parent 和只有 parent 不是 child 开始存在
  • 更快地绘制实时音频信号

    我有一段代码 它从笔记本电脑的音频插孔获取实时音频信号 并在进行一些基本过滤后绘制其图表 我面临的问题是 随着程序的运行 实时绘图变得越来越慢 有什么建议可以让绘图更快并以恒定的速度进行吗 我认为动画功能会使其更快 但无法根据我的要求制定
  • git diff 用于任何存储库之外的自定义 2 个文件?

    I need git diff我在任何存储库之外拥有的 2 个文件的功能 有办法做到吗 就像是git diff file1 path file1 txt file2 path file2 txt如果没有 替代解决方案是什么 答案就在the
  • 强制请求使用 IPv4 / IPv6

    如何强制requests库使用特定的互联网协议版本来获取请求 或者可以用Python中的另一种方法更好地实现这一点吗 我可以 但我不想使用curl 阐明目的的示例 import requests r requests get https m
  • 在 Woocommerce 3 中使用 WC_Cart add_to_cart() 方法存储自定义数据

    我正在创建一个会员网站 并为每个会员计划完全创建静态页面 只有 3 个计划 但是 我为每个计划添加了产品 当我点击 选择计划 按钮时 我会重定向到一些自定义表单 在其中询问用户我们将用于实现计划的信息范围 与sneakertub com相同
  • 如何使用 CGContext 获取像素的 RGB 值?

    我正在尝试通过更改像素来编辑图像 我有以下代码 let imageRect CGRectMake 0 0 self image image size width self image image size height UIGraphics