How to combine two image byte[] arrays together quickly utilizing a mask array in C#

岁酱吖の 提交于 2019-12-10 12:14:57

问题


In a nutshell I have two images I want to overlay one over the other using a mask so that only parts of the second image show up. This is part of a real time image processing routine so I need the operation to happen as fast as possible.

Specifically, I have two 32 bit image BGR byte arrays. In addition, I have a byte array that represents an image mask.

I want to generate a new byte array where byte array A is overlayed on top of byte array B using the mask array to decide which byte is used.

What is the quickest way to do this?

I was looking at this wikipedia article about old fashioned sprite masking but I am not sure how to best translate this to C#. http://en.wikipedia.org/wiki/Mask_(computing)

EDIT: I forgot to mention that I can restruct any or all of this to make it run faster.


回答1:


In principle, masking like this is very simple - assuming the arrays are the same size, this code would do it:

static void MaskImage(byte[] background, byte[] foreground, byte[] mask)
{
    for (var i = 0; i < background.Length; ++i)
    {
        background[i] &= mask[i];
        background[i] |= foreground[i];
    }
}

In a reality this will be quite a bit more complicated - your background is likely to be larger than whatever foreground image you're masking onto it, and you'll have to do some arithmetic to place it properly. While tedious to get right, it's not hard.




回答2:


This code doesn't work with individual byte arrays, but I worked on a project that required overlaying one image over another. Maybe this will help you.

http://pastebin.com/KXavA9Jr




回答3:


Third party tools are the way to go. I've used Lead Tools but there are many others.

If you want to do it yourself, you can use the LockBits method.

The best demonstration of LockBits is here: http://www.bobpowell.net/lockingbits.htm but the link is currently dead. Hopefully Mr. Powell will get this fixed.




回答4:


I might have misunderstood the question, but: you have two int arrays and a mask aray of the same size that applies the corresponding mask to both image arrays. Where a bit in the mask array is 0, you select the bit from A; when 1, you select the bit from b.

So if, for example, you had values in the first array element of:

 a[0]    : 0000 1111
 b[0]    : 0011 0011
 mask[0] : 0101 0101

Then the destination result would be:

 dest[i] : 0001 1011

This can be expressed as:

dest[i] = (a[i] AND (NOT MASK[i]))
          OR
          (b[i] AND MASK[i])

Or, in C#:

dest[i] = (a[i] & ~mask[i]) | (b[i] & mask[i]);

If this is the intent, then you can just run as a loop:

for (int i = 0; i < len; i++)
{
    dest[i] = (a[i] & ~mask[i]) | (b[i] & mask[i]); 
}

Finally, performance-wise, one note: you mention creating a new array to hold the destination image. If the images are of significant size, constantly creating large arrays can be a bottleneck. Instead, if possible, create the destination array once and reuse it as needed. Also, if you do need to allocate large numbers of byte arrays for transient use (e.g., within a method), you might want to consider using the stackalloc operator to allocate space on the stack, which can be more efficient than creating new managed arrays.



来源:https://stackoverflow.com/questions/6868680/how-to-combine-two-image-byte-arrays-together-quickly-utilizing-a-mask-array-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!