我有一个大图像 A 和另一个图像 B,它有一个我想粘贴到 A 中的 alpha 通道。我想在将其粘贴到 A 之前对 B 应用仿射变换。在 c++ 中执行此操作的步骤是什么在 iOS 中使用 vImage?
问问题
237 次
2 回答
1
我怀疑您是否能够获得此处发布的任何答案。他们只是没有足够的细节来帮助那些一开始就有这样的问题的人。
这是您的工作答案:
- (CVPixelBufferRef)copyRenderedPixelBuffer:(CVPixelBufferRef)pixelBuffer {
CVPixelBufferLockBaseAddress( pixelBuffer, 0 );
unsigned char *base = (unsigned char *)CVPixelBufferGetBaseAddress( pixelBuffer );
size_t width = CVPixelBufferGetWidth( pixelBuffer );
size_t height = CVPixelBufferGetHeight( pixelBuffer );
size_t stride = CVPixelBufferGetBytesPerRow( pixelBuffer );
//size_t extendedWidth = stride / sizeof( uint32_t ); // each pixel is 4 bytes/32 bits
vImage_Buffer _img = {
.data = base,
.height = height,
.width = width,
.rowBytes = stride
};
size_t pixelBufferSize = (stride * height) / sizeof(uint8_t);
void* gBuffer = malloc(pixelBufferSize);
vImage_Buffer _dstG = {
.data = gBuffer,
.height = height / sizeof(uint8_t),
.width = width / sizeof(uint8_t),
.rowBytes = stride / sizeof(uint8_t)
};
vImage_Error err;
const uint8_t map[4] = { 3, 2, 1, 0 };
err = vImagePermuteChannels_ARGB8888(&_img, &_img, map, kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"Error: %ld", err);
err = vImageExtractChannel_ARGB8888(&_img, &_dstG, 2, kvImageNoError);
if (err != kvImageNoError)
NSLog(@"Error: %ld", err);
err = vImageEqualization_Planar8(&_dstG, &_dstG, kvImageNoError);
if (err != kvImageNoError)
NSLog(@"Error: %ld", err);
err = vImageContrastStretch_Planar8( &_dstG, &_dstG, kvImageNoError );
if (err != kvImageNoError)
NSLog(@"Error: %ld", err);
err = vImageOverwriteChannels_ARGB8888(&_dstG, &_img, &_img, 0x2, kvImageNoError);
if (err != kvImageNoError)
NSLog(@"Error: %ld", err);
err = vImagePermuteChannels_ARGB8888(&_img, &_img, map, kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"Error: %ld", err);
CVPixelBufferUnlockBaseAddress( pixelBuffer, 0 );
free(gBuffer);
return (CVPixelBufferRef)CFRetain( pixelBuffer );
}
于 2015-05-13T16:08:18.973 回答
0
假设每个组件 8 位,4 通道数据:
- 取消预乘 A -- vImageUnpremultiplyData_ARGB8888
- 从 B 中提取 alpha 通道 -- vImageExtractChannel_ARGB8888
- 变换 B -- vImageAffineWarp_Planar8
- 从 A 中提取 alpha 通道 -- vImageExtractChannel_ARGB8888
- 将两个 Alpha 通道相乘——vImagePremultiplyData_Planar8
- 将结果写入 A -- vImageOverwriteChannels_ARGB8888
- 预乘A——vImagePremultiplyData_ARGB8888
如果您真的想用 B 替换 A 的 alpha 而不是将它们组合在一起,请跳过第 4 步和第 5 步。
如果您在一条扫描线上完成所有 7 个步骤,然后再继续下一条扫描线,整个过程会运行得更快。kvImageDoNotTile 和 dispatch_apply() 可以很简单地用于多线程。
关于预乘:您可以选择是否对图像进行预乘。合成预乘图像的性能优势通常被夸大了。将非预乘图像合成到预乘表面仅比合成预乘图像多一点工作。预乘会导致大多数图像过滤器出现问题,导致一堆工作不预乘并再次预乘。它也会导致一些精度损失。正如你在上面看到的,如果图像没有被预乘,那么你想要做的操作就会变得简单得多。它可以是简单的步骤 2 和 6,也可以是使用 vImageSelectChannels_ARGB8888 / vImagePermuteChannelsWithMaskedInsert_ARGB8888() 的单通道。
于 2015-01-27T04:53:49.403 回答