简体   繁体   中英

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:

  1. Unpremultiply A -- vImageUnpremultiplyData_ARGB8888
  2. extract alpha channel from B -- vImageExtractChannel_ARGB8888
  3. transform B -- vImageAffineWarp_Planar8
  4. extract alpha channel from A -- vImageExtractChannel_ARGB8888
  5. multiply the two alpha channels together -- vImagePremultiplyData_Planar8
  6. write the result into A -- vImageOverwriteChannels_ARGB8888
  7. premultiply 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.

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. kvImageDoNotTile and dispatch_apply() can be used to multithread it fairly simply.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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