Files
opencv-wasm/modules/core/misc/objc/common/MatExt.swift
2022-05-06 01:58:53 +08:00

245 lines
10 KiB
Swift

//
// MatExt.swift
//
// Created by Giles Payne on 2020/01/19.
//
import Foundation
let OpenCVErrorDomain = "OpenCVErrorDomain"
enum OpenCVError : Int {
case IncompatibleDataType = 10001
case IncompatibleBufferSize
}
func throwIncompatibleDataType(typeName: String) throws {
throw NSError(
domain: OpenCVErrorDomain,
code: OpenCVError.IncompatibleDataType.rawValue,
userInfo: [
NSLocalizedDescriptionKey: "Incompatible Mat type \(typeName)"
]
)
}
func throwIncompatibleBufferSize(count: Int, channels: Int32) throws {
throw NSError(
domain: OpenCVErrorDomain,
code: OpenCVError.IncompatibleBufferSize.rawValue,
userInfo: [
NSLocalizedDescriptionKey: "Provided data element number \(count) should be multiple of the Mat channels count \(channels)"
]
)
}
public extension Mat {
convenience init(rows:Int32, cols:Int32, type:Int32, data:[Int8]) {
let dataObject = data.withUnsafeBufferPointer { Data(buffer: $0) }
self.init(rows: rows, cols: cols, type: type, data: dataObject)
}
convenience init(rows:Int32, cols:Int32, type:Int32, data:[Int8], step:Int) {
let dataObject = data.withUnsafeBufferPointer { Data(buffer: $0) }
self.init(rows: rows, cols: cols, type: type, data: dataObject, step:step)
}
@discardableResult func get(indices:[Int32], data:inout [Int8]) throws -> Int32 {
let channels = CvType.channels(Int32(type()))
if Int32(data.count) % channels != 0 {
try throwIncompatibleBufferSize(count: data.count, channels: channels)
} else if depth() != CvType.CV_8U && depth() != CvType.CV_8S {
try throwIncompatibleDataType(typeName: CvType.type(toString: type()))
}
let count = Int32(data.count)
return data.withUnsafeMutableBufferPointer { body in
return __get(indices as [NSNumber], count: count, byteBuffer: body.baseAddress!)
}
}
@discardableResult func get(indices:[Int32], data:inout [Double]) throws -> Int32 {
let channels = CvType.channels(Int32(type()))
if Int32(data.count) % channels != 0 {
try throwIncompatibleBufferSize(count: data.count, channels: channels)
} else if depth() != CvType.CV_64F {
try throwIncompatibleDataType(typeName: CvType.type(toString: type()))
}
let count = Int32(data.count)
return data.withUnsafeMutableBufferPointer { body in
return __get(indices as [NSNumber], count: count, doubleBuffer: body.baseAddress!)
}
}
@discardableResult func get(indices:[Int32], data:inout [Float]) throws -> Int32 {
let channels = CvType.channels(Int32(type()))
if Int32(data.count) % channels != 0 {
try throwIncompatibleBufferSize(count: data.count, channels: channels)
} else if depth() != CvType.CV_32F {
try throwIncompatibleDataType(typeName: CvType.type(toString: type()))
}
let count = Int32(data.count)
return data.withUnsafeMutableBufferPointer { body in
return __get(indices as [NSNumber], count: count, floatBuffer: body.baseAddress!)
}
}
@discardableResult func get(indices:[Int32], data:inout [Int32]) throws -> Int32 {
let channels = CvType.channels(Int32(type()))
if Int32(data.count) % channels != 0 {
try throwIncompatibleBufferSize(count: data.count, channels: channels)
} else if depth() != CvType.CV_32S {
try throwIncompatibleDataType(typeName: CvType.type(toString: type()))
}
let count = Int32(data.count)
return data.withUnsafeMutableBufferPointer { body in
return __get(indices as [NSNumber], count: count, intBuffer: body.baseAddress!)
}
}
@discardableResult func get(indices:[Int32], data:inout [Int16]) throws -> Int32 {
let channels = CvType.channels(Int32(type()))
if Int32(data.count) % channels != 0 {
try throwIncompatibleBufferSize(count: data.count, channels: channels)
} else if depth() != CvType.CV_16U && depth() != CvType.CV_16S {
try throwIncompatibleDataType(typeName: CvType.type(toString: type()))
}
let count = Int32(data.count)
return data.withUnsafeMutableBufferPointer { body in
return __get(indices as [NSNumber], count: count, shortBuffer: body.baseAddress!)
}
}
@discardableResult func get(row: Int32, col: Int32, data:inout [Int8]) throws -> Int32 {
return try get(indices: [row, col], data: &data)
}
@discardableResult func get(row: Int32, col: Int32, data:inout [Double]) throws -> Int32 {
return try get(indices: [row, col], data: &data)
}
@discardableResult func get(row: Int32, col: Int32, data:inout [Float]) throws -> Int32 {
return try get(indices: [row, col], data: &data)
}
@discardableResult func get(row: Int32, col: Int32, data:inout [Int32]) throws -> Int32 {
return try get(indices: [row, col], data: &data)
}
@discardableResult func get(row: Int32, col: Int32, data:inout [Int16]) throws -> Int32 {
return try get(indices: [row, col], data: &data)
}
@discardableResult func put(indices:[Int32], data:[Int8]) throws -> Int32 {
let channels = CvType.channels(Int32(type()))
if Int32(data.count) % channels != 0 {
try throwIncompatibleBufferSize(count: data.count, channels: channels)
} else if depth() != CvType.CV_8U && depth() != CvType.CV_8S {
try throwIncompatibleDataType(typeName: CvType.type(toString: type()))
}
let count = Int32(data.count)
return data.withUnsafeBufferPointer { body in
return __put(indices as [NSNumber], count: count, byteBuffer: body.baseAddress!)
}
}
@discardableResult func put(indices:[Int32], data:[Int8], offset: Int, length: Int32) throws -> Int32 {
let channels = CvType.channels(Int32(type()))
if Int32(data.count) % channels != 0 {
try throwIncompatibleBufferSize(count: data.count, channels: channels)
} else if depth() != CvType.CV_8U && depth() != CvType.CV_8S {
try throwIncompatibleDataType(typeName: CvType.type(toString: type()))
}
return data.withUnsafeBufferPointer { body in
return __put(indices as [NSNumber], count: length, byteBuffer: body.baseAddress! + offset)
}
}
// unlike other put:indices:data functions this one (with [Double]) should convert input values to correct type
@discardableResult func put(indices:[Int32], data:[Double]) throws -> Int32 {
let channels = CvType.channels(Int32(type()))
if Int32(data.count) % channels != 0 {
try throwIncompatibleBufferSize(count: data.count, channels: channels)
}
if depth() == CvType.CV_64F {
let count = Int32(data.count)
return data.withUnsafeBufferPointer { body in
return __put(indices as [NSNumber], count: count, doubleBuffer: body.baseAddress!)
}
} else {
return __put(indices as [NSNumber], data: data as [NSNumber])
}
}
@discardableResult func put(indices:[Int32], data:[Float]) throws -> Int32 {
let channels = CvType.channels(Int32(type()))
if Int32(data.count) % channels != 0 {
try throwIncompatibleBufferSize(count: data.count, channels: channels)
} else if depth() != CvType.CV_32F {
try throwIncompatibleDataType(typeName: CvType.type(toString: type()))
}
let count = Int32(data.count)
return data.withUnsafeBufferPointer { body in
return __put(indices as [NSNumber], count: count, floatBuffer: body.baseAddress!)
}
}
@discardableResult func put(indices:[Int32], data:[Int32]) throws -> Int32 {
let channels = CvType.channels(Int32(type()))
if Int32(data.count) % channels != 0 {
try throwIncompatibleBufferSize(count: data.count, channels: channels)
} else if depth() != CvType.CV_32S {
try throwIncompatibleDataType(typeName: CvType.type(toString: type()))
}
let count = Int32(data.count)
return data.withUnsafeBufferPointer { body in
return __put(indices as [NSNumber], count: count, intBuffer: body.baseAddress!)
}
}
@discardableResult func put(indices:[Int32], data:[Int16]) throws -> Int32 {
let channels = CvType.channels(Int32(type()))
if Int32(data.count) % channels != 0 {
try throwIncompatibleBufferSize(count: data.count, channels: channels)
} else if depth() != CvType.CV_16U && depth() != CvType.CV_16S {
try throwIncompatibleDataType(typeName: CvType.type(toString: type()))
}
let count = Int32(data.count)
return data.withUnsafeBufferPointer { body in
return __put(indices as [NSNumber], count: count, shortBuffer: body.baseAddress!)
}
}
@discardableResult func put(row: Int32, col: Int32, data:[Int8]) throws -> Int32 {
return try put(indices: [row, col], data: data)
}
@discardableResult func put(row: Int32, col: Int32, data: [Int8], offset: Int, length: Int32) throws -> Int32 {
return try put(indices: [row, col], data: data, offset: offset, length: length)
}
@discardableResult func put(row: Int32, col: Int32, data: [Double]) throws -> Int32 {
return try put(indices: [row, col], data: data)
}
@discardableResult func put(row: Int32, col: Int32, data: [Float]) throws -> Int32 {
return try put(indices: [row, col], data: data)
}
@discardableResult func put(row: Int32, col: Int32, data: [Int32]) throws -> Int32 {
return try put(indices: [row, col], data: data)
}
@discardableResult func put(row: Int32, col: Int32, data: [Int16]) throws -> Int32 {
return try put(indices: [row, col], data: data)
}
@discardableResult func get(row: Int32, col: Int32) -> [Double] {
return get(indices: [row, col])
}
@discardableResult func get(indices: [Int32]) -> [Double] {
return __get(indices as [NSNumber]) as! [Double]
}
}