vb.net 创建图像蒙版

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17772991/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 14:19:45  来源:igfitidea点击:

Create Image Mask

c#.netvb.netimagebitmap

提问by Elmo

The user provides my app an image, from which the app needs to make a mask:

用户向我的应用提供了一张图片,应用需要从中制作一个蒙版:

The mask contains a red pixel for each transparent pixel in the original image.

对于原始图像中的每个透明像素,蒙版包含一个红色像素。

I tried the following:

我尝试了以下方法:

Bitmap OrgImg = Image.FromFile(FilePath);
Bitmap NewImg = new Bitmap(OrgImg.Width, OrgImg.Height);
for (int y = 0; y <= OrgImg.Height - 1; y++) {
    for (int x = 0; x <= OrgImg.Width - 1; x++) {
        if (OrgImg.GetPixel(x, y).A != 255) {
            NewImg.SetPixel(x, y, Color.FromArgb(255 - OrgImg.GetPixel(x, y).A, 255, 0, 0));
        }
    }
}
OrgImg.Dispose();
PictureBox1.Image = NewImg;

I am worried about the performance on slow PCs. Is there a better approach to do this?

我担心在慢速 PC 上的性能。有没有更好的方法来做到这一点?

回答by dsfgsho

It is perfectly acceptable to use GetPixel()if it is only used sporadicly, e.g. on loading one image. However, if you want to do a more serious image processing, it is better to work directly with BitmapData. A small example:

GetPixel()如果只是偶尔使用它是完全可以接受的,例如在加载一个图像时。但是,如果要进行更严肃的图像处理,最好直接使用BitmapData。一个小例子:

//Load the bitmap
Bitmap image = (Bitmap)Image.FromFile("image.png"); 

//Get the bitmap data
var bitmapData = image.LockBits (
    new Rectangle (0, 0, image.Width, image.Height),
    ImageLockMode.ReadWrite, 
    image.PixelFormat
);

//Initialize an array for all the image data
byte[] imageBytes = new byte[bitmapData.Stride * image.Height];

//Copy the bitmap data to the local array
Marshal.Copy(bitmapData.Scan0,imageBytes,0,imageBytes.Length);

//Unlock the bitmap
image.UnlockBits(bitmapData);

//Find pixelsize
int pixelSize = Image.GetPixelFormatSize(image.PixelFormat);

// An example on how to use the pixels, lets make a copy
int x = 0;
int y = 0;
var bitmap = new Bitmap (image.Width, image.Height);

//Loop pixels
for(int i=0;i<imageBytes.Length;i+=pixelSize/8)
{
    //Copy the bits into a local array
    var pixelData = new byte[3];
    Array.Copy(imageBytes,i,pixelData,0,3);

    //Get the color of a pixel
    var color = Color.FromArgb (pixelData [0], pixelData [1], pixelData [2]);

    //Set the color of a pixel
    bitmap.SetPixel (x,y,color);

    //Map the 1D array to (x,y)
    x++;
    if( x >= bitmap.Width)
    {
        x=0;
        y++;
    }

}

//Save the duplicate
bitmap.Save ("image_copy.png");

回答by Vadim

This approach is indeed slow. A better approach would be using Lockbits and access the underlying matrix directly. Take a look at http://bobpowell.net/lockingbits.aspxor http://www.mfranc.com/programming/operacje-na-bitmapkach-net-1/or http://msdn.microsoft.com/en-us/library/5ey6h79d.aspxor other articles about lockbits in StackOverflow.

这种方法确实很慢。更好的方法是使用 Lockbits 并直接访问底层矩阵。看看http://bobpowell.net/lockingbits.aspxhttp://www.mfranc.com/programming/operacje-na-bitmapkach-net-1/http://msdn.microsoft.com/en -us/library/5ey6h79d.aspx或其他关于 StackOverflow 中锁位的文章。

It's a tiny bit more complex since you'll have to work with bytes directly (4 per pixel if you're working with RGBA), but the performance boost is significant and is well worth it.

它稍微复杂一点,因为您必须直接使用字节(如果您使用 RGBA,则为每像素 4 个),但性能提升是显着的,非常值得。

Another note - OrgImg.GetPixel(x, y) is slow, if you're sticking with this (and not lockbits) make sure you only use it once (it may be already optimized, just check if there's a difference).

另一个注意事项 - OrgImg.GetPixel(x, y) 很慢,如果您坚持使用它(而不是锁定位),请确保您只使用它一次(它可能已经优化,只需检查是否存在差异)。