繁体   English   中英

如何在iOS中使用vImage旋转和粘贴具有Alpha通道的图像?

[英]How can I rotate and paste image with alpha channel using vImage in ios?

我有一个大图像A和另一个图像B,该图像具有要粘贴到A中的Alpha通道。我想在将B贴上A之前对其进行仿射变换。在c ++中执行此步骤的步骤是什么在iOS中使用vImage?

我怀疑您是否可以在此处发布任何答案才能正常工作; 只是其中没有足够的细节来帮助遇到此类问题的人。

这是您的工作答案:

- (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 );

}

假设每个组件8位,则4通道数据:

  1. 取消预乘A-vImageUnpremultiplyData_ARGB8888
  2. 从B提取alpha通道-vImageExtractChannel_ARGB8888
  3. 变换B-vImageAffineWarp_Planar8
  4. 从A提取alpha通道-vImageExtractChannel_ARGB8888
  5. 将两个Alpha通道相乘-vImagePremultiplyData_Planar8
  6. 将结果写入A-vImageOverwriteChannels_ARGB8888
  7. 预乘A-vImagePremultiplyData_ARGB8888

如果您确实想用B代替A的alpha而不是将它们组合在一起,请跳过第4步和第5步。

如果在转到下一条扫描线之前在一条扫描线上执行所有7个步骤,则整个过程将运行得更快。 kvImageDoNotTile和dispatch_apply()可用于相当简单地对其进行多线程处理。

关于预倍增:您可以选择是否对图像进行预倍增。 通常会夸大预合成图像的性能优势。 将未预乘的图像合成到预乘的曲面中,仅比将预乘的图像合成要多得多。 预乘会导致大多数图像滤镜出现问题,从而导致一堆工作无法进行预乘并再次进行预乘。 这也会导致一些精度损失。 正如您在上面看到的,如果图像没有预乘,那么您要执行的操作将变得更加简单。 只需第2步和第6步就可以很简单,也可以单次使用vImageSelectChannels_ARGB8888 / vImagePermuteChannelsWithMaskedInsert_ARGB8888()。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM