gpt4 book ai didi

swift - 访问已使用 Padding 扩展的 CVPixelBuffer 之外的像素

转载 作者:行者123 更新时间:2023-11-30 10:57:53 25 4
gpt4 key购买 nike

我正在尝试扩展 CVPixelBuffer,以便通过使用填充重新初始化 CVPixelBuffer 来访问缓冲区外部的内存不会导致 EXC_BAD_ACCESS 错误。然而,它似乎不起作用。任何有关我做错的事情的提示将不胜感激。

    let paddingLeft = abs(min(cropX, 0))
let paddingRight = max((cropX + cropWidth) - (srcWidth - 1), 0)
let paddingBottom = max((cropY + cropHeight) - (srcHeight - 1), 0)
let paddingTop = abs(min(cropY, 0))

let attr = [kCVPixelBufferExtendedPixelsLeftKey: paddingLeft*40 + 1 as CFNumber,
kCVPixelBufferExtendedPixelsTopKey: paddingTop*40 + 1 as CFNumber,
kCVPixelBufferExtendedPixelsRightKey: paddingRight*40 + 1 as CFNumber,
kCVPixelBufferExtendedPixelsBottomKey: paddingBottom*40 + 1 as CFNumber]

guard kCVReturnSuccess == CVPixelBufferCreateWithBytes(kCFAllocatorDefault, srcWidth, srcHeight, pixelFormat, srcData, srcBytesPerRow, nil, nil, attr as CFDictionary, &paddedSrcPixelBuffer) else {
print("failed to allocate a new padded pixel buffer")
return nil
}

使用扩展的 CVPixelBuffer,访问 CVPixelBuffer 之外的数据(例如当 x,y 为负或大于缓冲区的宽度/高度时)应该根据我的理解定义行为。然而,以下代码在 VImageScale_ARGB8888 内部的最后一行崩溃,EXC_BAD_ACCESS 代码为 1。

这大概意味着正在访问的数据未被映射。

guard let paddedSrcData = CVPixelBufferGetBaseAddress(paddedSrcPixelBuffer) else {
print("Error: could not get padded pixel buffer base address")
return nil
}

srcBuffer = vImage_Buffer(data: paddedSrcData.advanced(by: offset),
height: vImagePixelCount(cropHeight),
width: vImagePixelCount(cropWidth),
rowBytes: srcBytesPerRow)
let destBytesPerRow = scaleWidth*4
let destData = malloc(scaleHeight*destBytesPerRow)

var destBuffer = vImage_Buffer(data: destData,
height: vImagePixelCount(scaleHeight),
width: vImagePixelCount(scaleWidth),
rowBytes: destBytesPerRow)

let vImageFlags: vImage_Flags = vImage_Flags(kvImageEdgeExtend)
let error = vImageScale_ARGB8888(&srcBuffer, &destBuffer, nil, vImageFlags) // crashes here due to EXC_BAD_ACCESS Code: 1

非常感谢!

最佳答案

这是调整大小函数的修改版本,它将通过将连续的内存部分复制到具有正确形状的新分配的缓冲区中来创建填充缓冲区。

public func resizePixelBuffer(_ srcPixelBuffer: CVPixelBuffer,
cropX: Int,
cropY: Int,
cropWidth: Int,
cropHeight: Int,
scaleWidth: Int,
scaleHeight: Int) -> CVPixelBuffer? {
let flags = CVPixelBufferLockFlags(rawValue: 0)
let pixelFormat = CVPixelBufferGetPixelFormatType(srcPixelBuffer)
guard kCVReturnSuccess == CVPixelBufferLockBaseAddress(srcPixelBuffer, flags) else {
return nil
}
defer { CVPixelBufferUnlockBaseAddress(srcPixelBuffer, flags) }

guard let srcData = CVPixelBufferGetBaseAddress(srcPixelBuffer) else {
print("Error: could not get pixel buffer base address")
return nil
}

let srcHeight = CVPixelBufferGetHeight(srcPixelBuffer)
let srcWidth = CVPixelBufferGetWidth(srcPixelBuffer)
let srcBytesPerRow = CVPixelBufferGetBytesPerRow(srcPixelBuffer)
let offset = cropY*srcBytesPerRow + cropX*4

var srcBuffer: vImage_Buffer!
var paddedSrcPixelBuffer: CVPixelBuffer!

if (cropX < 0 || cropY < 0 || cropX + cropWidth > srcWidth || cropY + cropHeight > srcHeight) {
let paddingLeft = abs(min(cropX, 0))
let paddingRight = max((cropX + cropWidth) - (srcWidth - 1), 0)
let paddingBottom = max((cropY + cropHeight) - (srcHeight - 1), 0)
let paddingTop = abs(min(cropY, 0))

let paddedHeight = paddingTop + srcHeight + paddingBottom
let paddedWidth = paddingLeft + srcWidth + paddingRight

guard kCVReturnSuccess == CVPixelBufferCreate(kCFAllocatorDefault, paddedWidth, paddedHeight, pixelFormat, nil, &paddedSrcPixelBuffer) else {
print("failed to allocate a new padded pixel buffer")
return nil
}

guard kCVReturnSuccess == CVPixelBufferLockBaseAddress(paddedSrcPixelBuffer, flags) else {
return nil
}

guard let paddedSrcData = CVPixelBufferGetBaseAddress(paddedSrcPixelBuffer) else {
print("Error: could not get padded pixel buffer base address")
return nil
}

let paddedBytesPerRow = CVPixelBufferGetBytesPerRow(paddedSrcPixelBuffer)
for yIndex in paddingTop..<srcHeight+paddingTop {
let dstRowStart = paddedSrcData.advanced(by: yIndex*paddedBytesPerRow).advanced(by: paddingLeft*4)
let srcRowStart = srcData.advanced(by: (yIndex - paddingTop)*srcBytesPerRow)
dstRowStart.copyMemory(from: srcRowStart, byteCount: srcBytesPerRow)
}

let paddedOffset = (cropY + paddingTop)*paddedBytesPerRow + (cropX + paddingLeft)*4
srcBuffer = vImage_Buffer(data: paddedSrcData.advanced(by: paddedOffset),
height: vImagePixelCount(cropHeight),
width: vImagePixelCount(cropWidth),
rowBytes: paddedBytesPerRow)

} else {
srcBuffer = vImage_Buffer(data: srcData.advanced(by: offset),
height: vImagePixelCount(cropHeight),
width: vImagePixelCount(cropWidth),
rowBytes: srcBytesPerRow)
}

let destBytesPerRow = scaleWidth*4
guard let destData = malloc(scaleHeight*destBytesPerRow) else {
print("Error: out of memory")
return nil
}
var destBuffer = vImage_Buffer(data: destData,
height: vImagePixelCount(scaleHeight),
width: vImagePixelCount(scaleWidth),
rowBytes: destBytesPerRow)

let vImageFlags: vImage_Flags = vImage_Flags(kvImageEdgeExtend)
let error = vImageScale_ARGB8888(&srcBuffer, &destBuffer, nil, vImageFlags)
if error != kvImageNoError {
print("Error:", error)
free(destData)
return nil
}

let releaseCallback: CVPixelBufferReleaseBytesCallback = { _, ptr in
if let ptr = ptr {
free(UnsafeMutableRawPointer(mutating: ptr))
}
}

var dstPixelBuffer: CVPixelBuffer?
let status = CVPixelBufferCreateWithBytes(nil, scaleWidth, scaleHeight,
pixelFormat, destData,
destBytesPerRow, releaseCallback,
nil, nil, &dstPixelBuffer)
if status != kCVReturnSuccess {
print("Error: could not create new pixel buffer")
free(destData)
return nil
}

if paddedSrcPixelBuffer != nil {
CVPixelBufferUnlockBaseAddress(paddedSrcPixelBuffer, flags)
}


return dstPixelBuffer
}

关于swift - 访问已使用 Padding 扩展的 CVPixelBuffer 之外的像素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53734335/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com