问题
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