gpt4 book ai didi

ios - 为什么我使用以下代码得到错误的像素颜色?

转载 作者:搜寻专家 更新时间:2023-10-30 22:24:18 24 4
gpt4 key购买 nike

我创建了一个背景颜色为 RED 的 UIImage:

let theimage:UIImage=imageWithColor(UIColor(red: 1, green: 0, blue: 0, alpha: 1) );

func imageWithColor(color: UIColor) -> UIImage {
let rect = CGRectMake(0.0, 0.0, 200.0, 200.0)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()

CGContextSetFillColorWithColor(context, color.CGColor)
CGContextFillRect(context, rect)

let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

return image
}

我正在检索图像中间的颜色,如下所示:

let h:CGFloat=theimage.size.height;
let w:CGFloat=theimage.size.width;


let test:UIColor=theimage.getPixelColor(CGPoint(x: 100, y: 100))

var rvalue:CGFloat = 0;
var gvalue:CGFloat = 0;
var bvalue:CGFloat = 0;
var alfaval:CGFloat = 0;
test.getRed(&rvalue, green: &gvalue, blue: &bvalue, alpha: &alfaval);


print("Blue Value : " + String(bvalue));
print("Red Value : " + String(rvalue));


extension UIImage {
func getPixelColor(pos: CGPoint) -> UIColor {

let pixelData = CGDataProviderCopyData(CGImageGetDataProvider(self.CGImage))
let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)

let pixelInfo: Int = ((Int(self.size.width) * Int(pos.y)) + Int(pos.x)) * 4

let r = CGFloat(data[pixelInfo]) / CGFloat(255.0)
let g = CGFloat(data[pixelInfo+1]) / CGFloat(255.0)
let b = CGFloat(data[pixelInfo+2]) / CGFloat(255.0)
let a = CGFloat(data[pixelInfo+3]) / CGFloat(255.0)

return UIColor(red: r, green: g, blue: b, alpha: a)
}
}

结果我得到:

蓝色值:1.0红色值:0.0

这是为什么?我找不到错误。

最佳答案

问题不在于内置的 getRed 函数,而在于从提供程序数据中的各个颜色组件构建 UIColor 对象的函数。您的代码假设提供程序数据以 RGBA 格式存储,但显然不是。它似乎是 ARGB 格式。另外,我也不确定您的字节顺序是否正确。

当您有图像时,可以通过多种方式将其打包到提供者数据中。 Quartz 2D Programming Guide 中显示了一些示例:

enter image description here

如果您要为特定格式硬编码的 getPixelColor 例程,我可能会检查 alphaInfobitmapInfo 像这样(在 Swift 4.2 中):

extension UIImage {
func getPixelColor(point: CGPoint) -> UIColor? {
guard let cgImage = cgImage,
let pixelData = cgImage.dataProvider?.data
else { return nil }

let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)

let alphaInfo = cgImage.alphaInfo
assert(alphaInfo == .premultipliedFirst || alphaInfo == .first || alphaInfo == .noneSkipFirst, "This routine expects alpha to be first component")

let byteOrderInfo = cgImage.byteOrderInfo
assert(byteOrderInfo == .order32Little || byteOrderInfo == .orderDefault, "This routine expects little-endian 32bit format")

let bytesPerRow = cgImage.bytesPerRow
let pixelInfo = Int(point.y) * bytesPerRow + Int(point.x) * 4;

let a: CGFloat = CGFloat(data[pixelInfo+3]) / 255
let r: CGFloat = CGFloat(data[pixelInfo+2]) / 255
let g: CGFloat = CGFloat(data[pixelInfo+1]) / 255
let b: CGFloat = CGFloat(data[pixelInfo ]) / 255

return UIColor(red: r, green: g, blue: b, alpha: a)
}
}

如果您始终以编程方式为依赖于位图信息的代码构建此图像,我会在创建图像时明确指定这些细节:

func image(with color: UIColor, size: CGSize) -> UIImage? {
let rect = CGRect(origin: .zero, size: size)
let colorSpace = CGColorSpaceCreateDeviceRGB()
guard let context = CGContext(data: nil,
width: Int(rect.width),
height: Int(rect.height),
bitsPerComponent: 8,
bytesPerRow: Int(rect.width) * 4,
space: colorSpace,
bitmapInfo: CGBitmapInfo.byteOrder32Little.rawValue | CGImageAlphaInfo.premultipliedFirst.rawValue) else {
return nil
}
context.setFillColor(color.cgColor)
context.fill(rect)
return context.makeImage().flatMap { UIImage(cgImage: $0) }
}

也许更好,如 Technical Q&A 1509 所示,您可能希望 getPixelData 显式创建其自己的预定格式的上下文,将图像绘制到该上下文,现在代码不取决于您要应用的原始图像的格式这个。

extension UIImage {

func getPixelColor(point: CGPoint) -> UIColor? {
guard let cgImage = cgImage else { return nil }

let width = Int(size.width)
let height = Int(size.height)
let colorSpace = CGColorSpaceCreateDeviceRGB()

guard let context = CGContext(data: nil,
width: width,
height: height,
bitsPerComponent: 8,
bytesPerRow: width * 4,
space: colorSpace,
bitmapInfo: CGBitmapInfo.byteOrder32Little.rawValue | CGImageAlphaInfo.premultipliedFirst.rawValue)
else {
return nil
}

context.draw(cgImage, in: CGRect(origin: .zero, size: size))

guard let pixelBuffer = context.data else { return nil }

let pointer = pixelBuffer.bindMemory(to: UInt32.self, capacity: width * height)
let pixel = pointer[Int(point.y) * width + Int(point.x)]

let r: CGFloat = CGFloat(red(for: pixel)) / 255
let g: CGFloat = CGFloat(green(for: pixel)) / 255
let b: CGFloat = CGFloat(blue(for: pixel)) / 255
let a: CGFloat = CGFloat(alpha(for: pixel)) / 255

return UIColor(red: r, green: g, blue: b, alpha: a)
}

private func alpha(for pixelData: UInt32) -> UInt8 {
return UInt8((pixelData >> 24) & 255)
}

private func red(for pixelData: UInt32) -> UInt8 {
return UInt8((pixelData >> 16) & 255)
}

private func green(for pixelData: UInt32) -> UInt8 {
return UInt8((pixelData >> 8) & 255)
}

private func blue(for pixelData: UInt32) -> UInt8 {
return UInt8((pixelData >> 0) & 255)
}

private func rgba(red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8) -> UInt32 {
return (UInt32(alpha) << 24) | (UInt32(red) << 16) | (UInt32(green) << 8) | (UInt32(blue) << 0)
}

}

显然,如果您要检查一堆像素,您需要重构它(将标准化像素缓冲区的创建与检查颜色的代码分离),但希望这能说明这个想法。


对于早期版本的 Swift,请参阅 previous revision这个答案。

关于ios - 为什么我使用以下代码得到错误的像素颜色?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34593706/

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