简体   繁体   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?

I doubt you were able to get any of the answers posted here to work; 我怀疑您是否可以在此处发布任何答案才能正常工作; there are just not enough specifics in them to help someone who had a question like this to begin with. 只是其中没有足够的细节来帮助遇到此类问题的人。

Here's your working answer: 这是您的工作答案:

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

} }

Assuming 8-bits per component, 4 channel data: 假设每个组件8位,则4通道数据:

  1. Unpremultiply A -- vImageUnpremultiplyData_ARGB8888 取消预乘A-vImageUnpremultiplyData_ARGB8888
  2. extract alpha channel from B -- vImageExtractChannel_ARGB8888 从B提取alpha通道-vImageExtractChannel_ARGB8888
  3. transform B -- vImageAffineWarp_Planar8 变换B-vImageAffineWarp_Planar8
  4. extract alpha channel from A -- vImageExtractChannel_ARGB8888 从A提取alpha通道-vImageExtractChannel_ARGB8888
  5. multiply the two alpha channels together -- vImagePremultiplyData_Planar8 将两个Alpha通道相乘-vImagePremultiplyData_Planar8
  6. write the result into A -- vImageOverwriteChannels_ARGB8888 将结果写入A-vImageOverwriteChannels_ARGB8888
  7. premultiply A -- vImagePremultiplyData_ARGB8888 预乘A-vImagePremultiplyData_ARGB8888

If you really wanted to replace the alpha of A with B rather than composite them together, skip steps 4 and 5. 如果您确实想用B代替A的alpha而不是将它们组合在一起,请跳过第4步和第5步。

The whole thing will run quite a bit faster if you do all 7 steps on one scanline, before moving on to the next scanline. 如果在转到下一条扫描线之前在一条扫描线上执行所有7个步骤,则整个过程将运行得更快。 kvImageDoNotTile and dispatch_apply() can be used to multithread it fairly simply. kvImageDoNotTile和dispatch_apply()可用于相当简单地对其进行多线程处理。

On premultiplication: You may have a choice as to whether the images are premultiplied or not. 关于预倍增:您可以选择是否对图像进行预倍增。 The performance benefits for compositing of premultiplied images is usually overstated. 通常会夸大预合成图像的性能优势。 It is only marginally more work to composite a non-premultiplied image into a premultiplied surface than it is to composite a premultiplied one. 将未预乘的图像合成到预乘的曲面中,仅比将预乘的图像合成要多得多。 Premultiplication causes problems for most image filters, resulting in a bunch of work unpremultiplying and premultiplying again. 预乘会导致大多数图像滤镜出现问题,从而导致一堆工作无法进行预乘并再次进行预乘。 It also causes some precision loss. 这也会导致一些精度损失。 As you can see above, if the images are not premultiplied, then the operations you want to do become much simpler. 正如您在上面看到的,如果图像没有预乘,那么您要执行的操作将变得更加简单。 It could be a simple as just steps 2 and 6, or a single pass with vImageSelectChannels_ARGB8888 / vImagePermuteChannelsWithMaskedInsert_ARGB8888(). 只需第2步和第6步就可以很简单,也可以单次使用vImageSelectChannels_ARGB8888 / vImagePermuteChannelsWithMaskedInsert_ARGB8888()。

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

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