0

我想做什么

我的最终目标是让数组数据(例如[Int], [UInt][Float]通过一个通用函数传递,该函数转换任何这些类型并输出[UInt8]像素数据的 0-255 值。这样我就可以创建一个指向该UInt8数据的指针CFData,从该指针创建一个(内置类型),然后最终将其提供CFData给 aCGDataProvider并将其作为输入以从中生成灰度图像CGImage.init()。(我认为这个过程可能更简单,但这就是我想出来的。)

我的阅读功能如下所示

    mutating func fromfileBI<T : BinaryInteger>(count : Int = 1) -> [T]?  {
    let byteSize = MemoryLayout<T>.stride
    var swiftTypeOut : [T] = []
    if count > 1 {
        swiftTypeOut = [T].init(repeating: 0, count: count)
        for i in 0...count-1 {
            swiftTypeOut[i] = data.subdata(in: off + i * byteSize..<off + (i + 1) * byteSize ).withUnsafeBytes{ $0.load(as: T.self )}
        }
        off += count * byteSize
    }
    else if count == 1 {
        swiftTypeOut =  [ data.subdata(in: off..<(off+1) * byteSize ).withUnsafeBytes{ $0.load(as: T.self )} ]
        off += byteSize
    }
    else if count == 0 {
        
        return []
    } else if count < 0 {
        print("Warning, fRead.int8Read( count : Int = 1) called with a negative count, returning empty array.")
        return []
    }
    return swiftTypeOut
}

然而, BinaryFloatingPoint (BF)也有一个相同的实体函数

mutating func fromfileBF<T : BinaryFloatingPoint>(count : Int = 1) -> [T]?

以及用于格式化图像数据的函数(这最后一步是我所关心的......所有数据都将进入图像,而无需共享数据的原始类型(数据将是 [UInt8] 从这里返回功能))。

这是符合BinaryInteger的类型。:

func formatArrayDataforImage<T>(dataSet : Array< T >, count:  Int, numpyTypeName : String = "") -> [UInt8]! where T: BinaryInteger {



var f32Data = [Float](repeating: 0, count: count)
let obj = f32Data as NSObject // Object to synchronise
var UInt8BytesOut = [UInt8](repeating: 0, count: count)

DispatchQueue.concurrentPerform(iterations: count){ index in
    synchronized(obj) {
        let dataSetValue = dataSet[index]
        f32Data[index] = Float( dataSetValue )
    }
} // This DispatchQueue thing was necessary when I was dealing with pointers as input, Now I dont know.

guard let max = f32Data.max() else { fatalError("Find max fail.")}
guard let min = f32Data.min() else { fatalError("find min fail.")}

for i in 0..<f32Data.count {
    f32Data[i] -= min
    f32Data[i] =  255 * f32Data[i] / max
    UInt8BytesOut[i] = UInt8( f32Data[i] )
    if i<100 {
        print(UInt8BytesOut[i])
    }
}

return UInt8BytesOut

我猜另一个formatArrayDataforImage<T: BinaryFloatingPoint>只会在哪里Float(dataSetValue)也应该起作用,我认为可以Float32转换为Float等等Float8。但是函数调用要求BinaryInteger一致性,所以我们会看到。

RAMBLE :(跳过它只是为了上下文)–––––––</p>

我已经修复了一个函数,它读取字节并将它们输出为所需的类型,我一直硬编码以将一个数据集加载为类型 [UInt16],这很有效。但我从一开始就知道我必须学习如何使类型的处理完全自动化。(项目代码有点尴尬......我知道我必须打开从源文件读取的字符串值以确定 Swift 数据类型一次......但我最终在阅读时经常需要这个开关,现在我可能不得不再次硬编码开关.. 我将如何让调用它的任何函数都知道 Swift 数据类型?我不想使用单独的情况,例如打开数据类型然后强制转换var example_variable = dataWhosTypeIKnowOnly_FromRawString as [Int32] // <--I know your type from hardcoding the switch 我怀疑我的问题的答案隐藏在这个答案的某个地方–<a href="https://stackoverflow.com/questions/15958830/c-sharp-generics-cast-generic-type-to-value-type" >C# 泛型:将泛型类型转换为值类型 但是鉴于我正在处理希望为创建指针指定我的泛型类型数组,我不确定这会如何改变事情。

––––––––。

END 希望一劳永逸地学习如何清楚正确地处理 Swift 类型。

4

1 回答 1

0

如果我理解正确,您只想formatArrayDataforImage接受任何 BinaryInteger 或 BinaryFloatingPoint 数组而不重写整个内容。

为此,请将其编写为浮点数,然后从整数版本中调用它。

我相信这是您的浮点版本:

func formatArrayDataforImage<Element>(dataSet: [Element]) -> [UInt8]
where Element: BinaryFloatingPoint {
    guard let max = dataSet.max() else { fatalError("Find max fail.")}
    guard let min = dataSet.min() else { fatalError("find min fail.")}

    // Note this is a little dangerous since it it crash if
    // min and max aren't in the range 0 - 1. I'd probably add
    // assertions at least.
    return dataSet.map { UInt8(255 * ($0 - min) / max) }
}

没有特别的理由将其转换为浮点数。它适用于任何 BinaryFloatingPoint。

然后为 BinaryInteger 调用它,您只需将值映射到浮点类型(如 Float),就像您目前正在做的那样。

func formatArrayDataforImage<Element>(dataSet: [Element]) -> [UInt8]
where Element: BinaryInteger  // <=== Note different `where` clause
{
    // Since this creates a [Float] it will call the other function
    formatArrayDataforImage(dataSet: dataSet.map(Float.init))
}

请注意,您的 concurrentPerform 正在尝试并行执行非法操作(您不能同时在多个线程上修改数组,即使您正在修改不同的索引也不行)。事实证明这并不重要,因为您的同步只是使 concurrentPerform 再次串行。所有这些代码都相当于我的dataSet.map(Float.init).

于 2021-07-12T02:40:09.090 回答