大きな画像 A と、A に貼り付けたいアルファ チャネルを持つ別の画像 B があります。A に貼り付ける前に、B にアフィン変換を適用したいと考えています。C++ でこれを行う手順は何ですか? iOS で vImage を使用していますか?
2 に答える
ここに投稿された回答のいずれかを機能させることができたとは思えません。そもそもこのような質問をした人を助けるのに十分な詳細がありません.
これがあなたの実用的な答えです:
- (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 チャネル データを想定すると、次のようになります。
- 前乗算解除 A -- vImageUnpremultiplyData_ARGB8888
- B からアルファチャンネルを抽出 -- vImageExtractChannel_ARGB8888
- 変換 B -- vImageAffineWarp_Planar8
- A からアルファチャンネルを抽出 -- vImageExtractChannel_ARGB8888
- 2 つのアルファ チャネルを乗算します -- vImagePremultiplyData_Planar8
- 結果を A に書き込みます -- vImageOverwriteChannels_ARGB8888
- premultiply A -- vImagePremultiplyData_ARGB8888
A を合成するのではなく、A のアルファを B に置き換えたい場合は、手順 4 と 5 をスキップしてください。
次のスキャンラインに移る前に、1 つのスキャンラインで 7 つのステップすべてを実行すると、全体がかなり速く実行されます。kvImageDoNotTile と dispatch_apply() を使用すると、かなり簡単にマルチスレッド化できます。
事前乗算について: 画像を事前乗算するかどうかを選択できます。あらかじめ乗算されたイメージを合成することによるパフォーマンス上の利点は、通常誇張されています。事前乗算された画像を合成するよりも、事前乗算されていない画像を事前乗算された表面に合成する方がわずかに手間がかかります。事前乗算は、ほとんどの画像フィルターで問題を引き起こし、その結果、事前乗算を解除して再度事前乗算を行うという大量の作業が発生します。また、精度の損失も発生します。上で見たように、画像が事前に乗算されていない場合、実行する操作ははるかに簡単になります。手順 2 と 6 だけの簡単な方法でも、vImageSelectChannels_ARGB8888 / vImagePermuteChannelsWithMaskedInsert_ARGB8888() を使用した単一パスでもかまいません。