【发布时间】:2022-02-15 20:48:20
【问题描述】:
我正在尝试更改 UIImage 的像素数据并使用新的像素数据创建新图像。我一直在尝试在以下指向 Swift 的链接中实现该功能。
https://galactic.ink/labs/Color-Vision/Javascript/Color.Vision.Daltonize.js
我不断遇到转换错误。
错误:无法将“UInt32”类型的值分配给“RGBA32”类型的下标
错误:无法将类型“RGBA32”的值转换为预期的参数类型“UInt32”
此外,我在处理算法中使用的数据类型是 UInt32,它不包含负数,所以我想知道是否有可能在 Swift 中编写这个方法。
var image = UIImage(named: "ME2.png")!
func processPixels(in image: UIImage) -> UIImage? {
guard let inputCGImage = image.cgImage else { print("unable to get cgImage")
return nil}
let colorSpace = CGColorSpaceCreateDeviceRGB()
let width = inputCGImage.width
let height = inputCGImage.height
let bytesPerPixel = 4
let bitsPerComponent = 8
let bytesPerRow = bytesPerPixel * width
let bitmapInfo = RGBA32.bitmapInfo
guard let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo) else {
print("unable to create context")
return nil
}
context.draw(inputCGImage, in: CGRect(x: 0, y: 0, width: width, height: height))
guard let buffer = context.data else {
print("unable to get context data")
return nil
}
let pixelBuffer = buffer.bindMemory(to: RGBA32.self, capacity: width * height)
let pro :[Float] = [0.0, 2.02344, -2.52581, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]
let a = pro[0];
let b = pro[1];
let c = pro[2];
let d = pro[3];
let e = pro[4];
let f = pro[5];
let g = pro[6];
let h = pro[7];
let i = pro[8];
var L : UInt32
var M : UInt32
var S : UInt32
var l : UInt32
var m : UInt32
var s : UInt32
var R : UInt32
var G : UInt32
var B : UInt32
var RR : UInt32
var GG : UInt32
var BB : UInt32
for y in 0 ..< inputCGImage.height {
for x in 0 ..< inputCGImage.width {
let offset = (y * inputCGImage.bytesPerRow) + (x * bytesPerPixel)
let r = pixelBuffer[offset]
let g = pixelBuffer[offset + 1]
let b = pixelBuffer[offset + 2]
let components = (r: pixelBuffer[offset], g: pixelBuffer[offset + 1], b: pixelBuffer[offset + 2])
print("[x:\(x), y:\(y)] \(components)")
//RGB To LMS matrix conversion
error: ColorPractice.playground:78:15: error: the compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
L = (UInt32(17.8824) * r) + (UInt32(43.5161) * g) + (UInt32(4.11935) * b);
error: ColorPractice.playground:79:15: error: the compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
M = (UInt32(3.45565) * r) + (UInt32(27.1554) * g) + (UInt32(3.86714) * b);
error: ColorPractice.playground:80:15: error: the compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
S = (UInt32(0.0299566) * r) + (UInt32(0.184309) * g) + (UInt32(1.46709) * b);
~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
L = (UInt32(17.8824) * r) + (UInt32(43.5161) * g) + (UInt32(4.11935) * b);
M = (UInt32(3.45565) * r) + (UInt32(27.1554) * g) + (UInt32(3.86714) * b);
S = (UInt32(0.0299566) * r) + (UInt32(0.184309) * g) + (UInt32(1.46709) * b);
//Simulate Color Blindness
error: ColorPractice.playground:86:36: error: no exact matches in call to initializer
l = (UInt32(a) * L) + (UInt32(b) * M) + (UInt32(c) * S);
error: ColorPractice.playground:88:18: error: no exact matches in call to initializer
s = (UInt32(g) * L) + (UInt32(h) * M) + (UInt32(i) * S);
~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
l = (UInt32(a) * L) + (UInt32(b) * M) + (UInt32(c) * S);
m = (UInt32(d) * L) + (UInt32(e) * M) + (UInt32(f) * S);
s = (UInt32(g) * L) + (UInt32(h) * M) + (UInt32(i) * S);
//LMS to RGB matrix conversion
R = (UInt32(0.0809444479) * l) + (UInt32(0.130504409) * m) + (UInt32(0.116721066) * s);
G = (UInt32(0.0102485335) * l) + (UInt32(0.0540193266) * m) + (UInt32(0.113614708) * s);
B = (UInt32(0.000365296938) * l) + (UInt32(0.00412161469) * m) + (UInt32(0.693511405) * s);
//Isolate invisible colors to color vision deficiency (calculate error matrix)
error: ColorPractice.playground:98:17: error: cannot convert value of type 'RGBA32' to expected argument type 'UInt32'
R = r - R;
^
error: ColorPractice.playground:99:17: error: cannot convert value of type 'RGBA32' to expected argument type 'UInt32'
G = g - G;
^
error: ColorPractice.playground:100:17: error: cannot convert value of type 'RGBA32' to expected argument type 'UInt32'
B = b - B;
^
~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
R = r - R;
G = g - G;
B = b - B;
//Shift colors towards visible spectrum (apply error modifications)
RR = (UInt32(0.0) * R) + (UInt32(0.0) * G) + (UInt32(0.0) * B);
GG = (UInt32(0.7) * R) + (UInt32(1.0) * G) + (UInt32(0.0) * B);
BB = (UInt32(0.7) * R) + (UInt32(0.0) * G) + (UInt32(1.0) * B);
//Add compensation to original values
error: ColorPractice.playground:108:22: error: cannot convert value of type 'RGBA32' to expected argument type 'UInt32'
R = RR + r;
^
error: ColorPractice.playground:109:22: error: cannot convert value of type 'RGBA32' to expected argument type 'UInt32'
G = GG + g;
^
error: ColorPractice.playground:110:22: error: cannot convert value of type 'RGBA32' to expected argument type 'UInt32'
B = BB + b;
^
~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
R = RR + r;
G = GG + g;
B = BB + b;
//Keep values in range
if(R < 0) {R = 0}
if(R > 255) {R = 255}
if(G < 0 ) {G = 0}
if(G > 255) {G = 255}
if (B < 0) {B = 0}
if (B > 255) {B = 255}
//Resassign Pixels in Array
error: ColorPractice.playground:123:37: error: cannot assign value of type 'UInt32' to subscript of type 'RGBA32'
pixelBuffer[offset] = R >> 0;
~~^~~~
error: ColorPractice.playground:124:41: error: cannot assign value of type 'UInt32' to subscript of type 'RGBA32'
pixelBuffer[offset + 1] = G >> 0;
~~^~~~
error: ColorPractice.playground:125:41: error: cannot assign value of type 'UInt32' to subscript of type 'RGBA32'
pixelBuffer[offset + 2] = B >> 0;
~~^~~~
~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pixelBuffer[offset] = R >> 0;
pixelBuffer[offset + 1] = G >> 0;
pixelBuffer[offset + 2] = B >> 0;
}
}
let outputCGImage = context.makeImage()!
let outputImage = UIImage(cgImage: outputCGImage, scale: image.scale, orientation: image.imageOrientation)
return outputImage
}
struct RGBA32: Equatable {
private var color: UInt32
var redComponent: UInt8 {
return UInt8((color >> 24) & 255)
}
var greenComponent: UInt8 {
return UInt8((color >> 16) & 255)
}
var blueComponent: UInt8 {
return UInt8((color >> 8) & 255)
}
var alphaComponent: UInt8 {
return UInt8((color >> 0) & 255)
}
init(red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8) {
let red = UInt32(red)
let green = UInt32(green)
let blue = UInt32(blue)
let alpha = UInt32(alpha)
color = (red << 24) | (green << 16) | (blue << 8) | (alpha << 0)
}
static let red = RGBA32(red: 255, green: 0, blue: 0, alpha: 255)
static let green = RGBA32(red: 0, green: 255, blue: 0, alpha: 255)
static let blue = RGBA32(red: 0, green: 0, blue: 255, alpha: 255)
static let white = RGBA32(red: 255, green: 255, blue: 255, alpha: 255)
static let black = RGBA32(red: 0, green: 0, blue: 0, alpha: 255)
static let magenta = RGBA32(red: 255, green: 0, blue: 255, alpha: 255)
static let yellow = RGBA32(red: 255, green: 255, blue: 0, alpha: 255)
static let cyan = RGBA32(red: 0, green: 255, blue: 255, alpha: 255)
static let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
static func ==(lhs: RGBA32, rhs: RGBA32) -> Bool {
return lhs.color == rhs.color
}
}
【问题讨论】:
-
真正的问题是什么?
-
为什么我的 RGBA 结构和转换算法中的变量之间会出现类型转换错误?
-
您的问题的哪一部分告诉我哪一行会引发错误?我错过了吗?
-
在代码中添加了错误语句。
-
酷。好的,那么这有什么难的呢?这似乎非常清楚。采取
UInt32(17.8824) * r。好吧,r是一个 RGBA32,它是一个非常复杂的结构。 UInt32 是一个数字。将它们相乘到底意味着什么?斯威夫特不知道,我也不知道。你呢?该表达式的目的是什么?
标签: swift core-image