作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在使用 CFDataGetBytePtr 时遇到一些问题。当我同时使用它加载 2 批图像数据到内存中进行像素颜色评估时,我发现一个数据集与另一个数据集相同,然后我做了一些挖掘,两个数据地址相同,我很不确定为什么.这是我处理这些事情的类(class)。
import Foundation
import UIKit
/// Helper class finds pixels values within the given image
class ImagePixelHelper
{
/// The image to find pixels in
private let image: UIImage
/// The image data
private var data:UnsafePointer<UInt8>?
/// The expected length of the image data
private var expectedLengthA:Int?
/// The expected rgb length of the image
private var expectedLengthRGB:Int?
/// The expected rgba length of the image
private var expectedLengthRGBA:Int?
/// The actual number of bytes in the image
private var numBytes: CFIndex?
/// Default constructor for the ImagePixelHelper
/// - Parameter image: The image to find pixels in
init(image: UIImage)
{
self.image = image
}
/// Function loads all the image data for quick access later
func loadImageData() throws
{
// Get the image as a CGImage
let cgImage : CGImage = image.cgImage!
// Get the pixel data
guard let pixelData = CGDataProvider(data: (cgImage.dataProvider?.data)!)?.data else{
fatalError()
}
// Get the pointer to the start of the array
data = CFDataGetBytePtr(pixelData)!
// Calculate the expected lengths
expectedLengthA = Int(image.size.width * image.size.height)
expectedLengthRGB = 3 * expectedLengthA!
expectedLengthRGBA = 4 * expectedLengthA!
// Get the length of the data
numBytes = CFDataGetLength(pixelData)
}
/// Function sets all member vars to nil to help speed up GC
func unloadImageData()
{
data = nil
expectedLengthA = nil
expectedLengthRGB = nil
expectedLengthRGBA = nil
numBytes = nil
}
/// Function gets the pixel colour from the given image using the provided x y coordinates
/// - Parameter pixelX: The X Pixel coordinate
/// - Parameter pixelY: The Y Pixel coordinate
/// - Parameter bgr: Whether we should return BGR, by default this is true so must be set if you want RGB
func getPixelValueFromImage(pixelX: Int, pixelY:Int, bgr: Bool = true) -> UIColor
{
// If we have all the required member vars for this operation
if let data = self.data,
let expectedLengthA = self.expectedLengthA,
let expectedLengthRGB = self.expectedLengthRGB,
let expectedLengthRGBA = self.expectedLengthRGBA,
let numBytes = self.numBytes
{
// Get the index of the pixel we want
let index = Int(image.size.width) * pixelY + pixelX
// Check the number of bytes
switch numBytes
{
case expectedLengthA:
return UIColor(red: 0, green: 0, blue: 0, alpha: CGFloat(data[index])/255.0)
case expectedLengthRGB:
if bgr
{
return UIColor(red: (CGFloat(data[3*index+2])/255.0).rounded(), green: (CGFloat(data[3*index+1])/255.0).rounded(), blue: (CGFloat(data[3*index])/255.0).rounded(), alpha: 1.0)
}
else
{
return UIColor(red: (CGFloat(data[3*index])/255.0).rounded(), green: (CGFloat(data[3*index+1])/255.0).rounded(), blue: (CGFloat(data[3*index+2])/255.0).rounded(), alpha: 1.0)
}
case expectedLengthRGBA:
if bgr
{
return UIColor(red: (CGFloat(data[4*index+2])/255.0).rounded(), green: (CGFloat(data[4*index+1])/255.0).rounded(), blue: (CGFloat(data[4*index])/255.0).rounded(), alpha: (CGFloat(data[4*index+3])/255.0).rounded())
}
else
{
return UIColor(red: (CGFloat(data[4*index])/255.0).rounded(), green: (CGFloat(data[4*index+1])/255.0).rounded(), blue: (CGFloat(data[4*index+2])/255.0).rounded(), alpha: (CGFloat(data[4*index+3])/255.0).rounded())
}
default:
// unsupported format
return UIColor.clear
}
}
else
{
// Something didnt load properly or has been destroyed
return UIColor.clear
}
}
}
所以当我加载 2 张图片时,我执行以下操作
let image1 = UIImage(named: "image1")!
let pixelHelper1 = BviNumberImagePixelHelper(image: image1)
try pixelHelper1()
let image2 = UIImage(named: "image2")!
let pixelHelper1 = BviNumberImagePixelHelper(image: UIImage(named: "image2")!)
try pixelHelper1()
当这段代码执行时,我在它之后有一个断点,并在两个 pixelHelper 对象上计算 ImagePixelHelper.data 的值,内存地址是相同的。
对这个问题有什么想法吗?这意味着当我循环图像时,他们会给出结果
最佳答案
问题是在
let pixelData = CGDataProvider(data: (cgImage.dataProvider?.data)!)?.data
CFData
实例被分配给一个局部变量,因此在 loadImageData()
函数返回时释放。下一次调用(可能使用不同的图像)会重新使用相同的内存。
分配
pixelData = CGDataProvider(data: (cgImage.dataProvider?.data)!)?.data
实例属性 反而解决了这个问题。现在,只要 ImagePixelHelper
实例存在,数据就会保留。
你可以进一步简化为
pixelData = cgImage.dataProvider?.data
关于Swift,Memory 解决了 CFDataGetBytePtr 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58452487/
在使用 CFDataGetBytePtr 时遇到一些问题。当我同时使用它加载 2 批图像数据到内存中进行像素颜色评估时,我发现一个数据集与另一个数据集相同,然后我做了一些挖掘,两个数据地址相同,我很不
我是一名优秀的程序员,十分优秀!