我使用Xcode Playground进入Swift,并且我正在关注简单图像过滤的在线课程。
到目前为止,这是我的代码:
import UIKit
let image = UIImage(named: "sample")!
let rgbaImage = RGBAImage(image: image)
class ImageInfo {
let rgbaImage = RGBAImage(image: image)
func getAvgCols() -> [String:Int] {
var totalRed = 0
var totalGreen = 0
var totalBlue = 0
var avgCol = [String:Int]()
for y in 0..<rgbaImage!.height{
for x in 0..<rgbaImage!.width{
let index = y * rgbaImage!.width + x
let pixel = rgbaImage!.pixels[index]
totalRed += Int(pixel.red)
totalGreen += Int(pixel.green)
totalBlue += Int(pixel.blue)
}
}
let pixelCount = rgbaImage!.width * rgbaImage!.height
avgCol["Red"] = (totalRed / pixelCount)
avgCol["Green"] = (totalGreen / pixelCount)
avgCol["Blue"] = (totalBlue / pixelCount)
return avgCol
}
}
let imageInfo = ImageInfo()
var avgRed = imageInfo.getAvgCols()["Red"]!
var avgGreen = imageInfo.getAvgCols()["Green"]!
var avgBlue = imageInfo.getAvgCols()["Blue"]!
var modifier = 20
// IMAGE EDITING LOOP
for y in 0..<rgbaImage!.height{
for x in 0..<rgbaImage!.width{
let index = y * rgbaImage!.width + x
var pixel = rgbaImage!.pixels[index]
let redDelta = Int(pixel.red) - avgRed
let greenDelta = Int(pixel.green) - avgGreen
let blueDelta = Int(pixel.blue) - avgBlue
let redModifier = Double(modifier) * 0.49
let greenModifier = Double(modifier) * 0.25
let blueModifier = Double(modifier) * 0.07
pixel.red = UInt8(max(min(255, avgRed + Int(redModifier) * redDelta),0))
pixel.green = UInt8(max(min(255, avgGreen + Int(greenModifier) * greenDelta),0))
pixel.blue = UInt8(max(min(255, avgBlue + Int(blueModifier) * blueDelta),0))
rgbaImage!.pixels[index] = pixel
}
}
let newImage = rgbaImage!.toUIImage()!
到目前为止,效果很好。最后一段代码基于每个像素修改图像,最终结果是一个穷人尝试一些棕褐色。
然而,问题在于我将整个图像编辑循环粘贴到另一个类中,如下所示:
class ImageEdit {
let imageInfo = ImageInfo()
var avgRed = imageInfo.getAvgCols()["Red"]!
var avgGreen = imageInfo.getAvgCols()["Green"]!
var avgBlue = imageInfo.getAvgCols()["Blue"]!
func applyFilter(filter: String, modifier: Int) -> UIImage{
for y in 0..<rgbaImage!.height{
for x in 0..<rgbaImage!.width{
let index = y * rgbaImage!.width + x
var pixel = rgbaImage!.pixels[index]
let redDelta = Int(pixel.red) - avgRed
let greenDelta = Int(pixel.green) - avgGreen
let blueDelta = Int(pixel.blue) - avgBlue
let redModifier = Double(modifier) * 0.49
let greenModifier = Double(modifier) * 0.25
let blueModifier = Double(modifier) * 0.07
pixel.red = UInt8(max(min(255, avgRed + Int(redModifier) * redDelta),0))
pixel.green = UInt8(max(min(255, avgGreen + Int(greenModifier) * greenDelta),0))
pixel.blue = UInt8(max(min(255, avgBlue + Int(blueModifier) * blueDelta),0))
rgbaImage!.pixels[index] = pixel
}
}
let newImage = rgbaImage!.toUIImage()!
return newImage
}
}
注意:由于我使用的是游戏场,因此两个类都在同一个文件中。为了澄清,只需使用我之前的代码,并将下面的下的所有内容ImageInfo
替换为ImageEdit
我需要访问avgRed,avgGreen和avgBlue,但我得到的只是
实例成员&#39; imageInfo&#39;不能在类型&#39; ImageEdit&#39;
上使用
由于我是Swift的菜鸟,我不确定如何修复它。
我错过了什么吗?
编辑:这里的RGBAImage。我没有写这个代码,可以免费下载给参加在线课程的任何人。
import UIKit
public struct Pixel {
public var value: UInt32
public var red: UInt8 {
get {
return UInt8(value & 0xFF)
}
set {
value = UInt32(newValue) | (value & 0xFFFFFF00)
}
}
public var green: UInt8 {
get {
return UInt8((value >> 8) & 0xFF)
}
set {
value = (UInt32(newValue) << 8) | (value & 0xFFFF00FF)
}
}
public var blue: UInt8 {
get {
return UInt8((value >> 16) & 0xFF)
}
set {
value = (UInt32(newValue) << 16) | (value & 0xFF00FFFF)
}
}
public var alpha: UInt8 {
get {
return UInt8((value >> 24) & 0xFF)
}
set {
value = (UInt32(newValue) << 24) | (value & 0x00FFFFFF)
}
}
}
public struct RGBAImage {
public var pixels: UnsafeMutableBufferPointer<Pixel>
public var width: Int
public var height: Int
public init?(image: UIImage) {
guard let cgImage = image.CGImage else { return nil }
// Redraw image for correct pixel format
let colorSpace = CGColorSpaceCreateDeviceRGB()
var bitmapInfo: UInt32 = CGBitmapInfo.ByteOrder32Big.rawValue
bitmapInfo |= CGImageAlphaInfo.PremultipliedLast.rawValue & CGBitmapInfo.AlphaInfoMask.rawValue
width = Int(image.size.width)
height = Int(image.size.height)
let bytesPerRow = width * 4
let imageData = UnsafeMutablePointer<Pixel>.alloc(width * height)
guard let imageContext = CGBitmapContextCreate(imageData, width, height, 8, bytesPerRow, colorSpace, bitmapInfo) else { return nil }
CGContextDrawImage(imageContext, CGRect(origin: CGPointZero, size: image.size), cgImage)
pixels = UnsafeMutableBufferPointer<Pixel>(start: imageData, count: width * height)
}
public func toUIImage() -> UIImage? {
let colorSpace = CGColorSpaceCreateDeviceRGB()
var bitmapInfo: UInt32 = CGBitmapInfo.ByteOrder32Big.rawValue
bitmapInfo |= CGImageAlphaInfo.PremultipliedLast.rawValue & CGBitmapInfo.AlphaInfoMask.rawValue
let bytesPerRow = width * 4
let imageContext = CGBitmapContextCreateWithData(pixels.baseAddress, width, height, 8, bytesPerRow, colorSpace, bitmapInfo, nil, nil)
guard let cgImage = CGBitmapContextCreateImage(imageContext) else {return nil}
let image = UIImage(CGImage: cgImage)
return image
}
}
答案 0 :(得分:1)
问题是您在初始化课程之前在imageInfo
内调用属性ImageEdit
。
只有在调用初始化时,一切都变成了某种东西。因此,avgRed
无法从imageInfo
函数中获取值,因为它尚未构建。
在函数内部执行此操作(init()
基本上是一个函数)只是找到。在课堂上这样做是行不通的。
这不起作用:
class A {
let attribute : Int = 0
init() {
}
}
class B {
let attributeA = A()
let attributeB = attributeA.attribute // this is your problem
}
这样做:
对于依赖于构建其他属性的所有属性,使用 late init 。所有依赖外部输入的属性,可用功能,......您声明为可选。
var / let attrName : Type
var / let attrName : Type ? / !
class B {
let attributeA = A()
let attributeB : Int
var attributeC : Int?
init () {
attributeB = attributeA.attribute
attributeC = somethingOptional()
}
func somethingOptional() -> Int? {
return 0 // not really optional, but just illustration
}
}
所以对你来说就是这样:
class ImageEdit {
let imageInfo = ImageInfo()
let dict : [String:Int]
init () {
dict = imageInfo.getAvgCols()
}
}