gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 00:52:21 25 4
gpt4 key购买 nike

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

我有以下代码:

    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 创建上下文,这样我们就可以确定字节顺序和颜色空间。

在我的 playground 中,我添加了一个名为 pic@2x.jpeg 的测试图像。

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 考虑了 image.orientationCGContextDrawImage 没有。

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

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

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

请注意,Pixel 成员的顺序定义为匹配我在 CGBitmapContextCreatebitmapInfo 参数中设置的特定位。

现在我们可以遍历像素了。请注意,我们使用上面计算的 rowCountcolumnCount 来访问所有像素,而不考虑图像比例:

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)

结果,在我的 playground 时间轴中:

timeline screenshot

最后,请注意,如果您的图片很大,逐个像素地处理可能会很慢。如果你能找到一种使用 Core Image 或 GPUImage 执行图像处理的方法,它会快得多。如果做不到这一点,使用 Objective-C 并手动对其进行矢量化(使用 NEON 内在函数)可能会提供很大的提升。

关于ios - 如何使用 CGContext 获取像素的 RGB 值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33214508/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com