2014-08-27 111 views
1

我使用C#的位图对象上MakeTransparent()函数调用将图像转换为透明图像。当这个方法被调用时,它会通过设置alpha通道将背景颜色转换为透明,然后将背景颜色转换为黑色。我设置得比黑色()与makeTransparent创建图像以外的颜色如何

我需要找到将这个背景色回白色或快速的方式无论原来的颜色了,因为有时我需要将图像拼合到非alpha通道启用格式。

制作透明似乎并不具有允许你告诉它独自离开的背景颜色任何标志或过载,并通过改变像素的图像像素是方式效率低下。任何人有任何建议或GDI技巧来解决这个问题?

+2

这是你不得不面对的内部优化。如果你想让背景变成白色,那么就把它画在白色的背景上。如果你想恢复原始背景颜色,那么你必须记住它是什么。 – 2014-08-27 19:23:43

+0

我可以编写一个函数与背景拼合图像,但它似乎应该有一个简单的解决方案。 – MadTigger 2014-08-27 20:59:58

+0

然后,请不要使用该功能。手动做。 – Nyerguds 2018-01-03 12:16:08

回答

0

似乎有不是一个快速的方法来做到这一点使用托管代码接口。使用单独的像素操作,或使用非托管代码更新像素似乎是唯一真正的选择。

0

这实际上可以在托管代码中使用Marshal.Copy将备份字节数组复制出位图对象,然后对其进行编辑,然后将其复制回来。

因此,基本上,在记住,一般的方法,你只是去以上的像素,逐行,检测哪个像素有你想要更换的颜色,他们的阿尔法字节设置为0

注意“ ARGB“是指一个读像素的值在Int32值内的顺序。由于这个值是小端的,所以给定偏移处的字节的实际顺序是相反的; B =偏移+ 0,G = OFFSET + 1,R = OFFSET + 2,A =偏移+ 3.

/// <summary> 
/// Clears the alpha value of all pixels matching the given colour. 
/// </summary> 
public static Bitmap MakeTransparentKeepColour(Bitmap image, Color clearColour) 
{ 
    Int32 width = image.Width; 
    Int32 height = image.Height; 
    // Paint on 32bppargb, so we're sure of the byte data format 
    Bitmap bm32 = new Bitmap(width, height, PixelFormat.Format32bppArgb); 
    using (Graphics gr = Graphics.FromImage(bm32)) 
     gr.DrawImage(image, new Rectangle(0, 0, width, height)); 

    BitmapData sourceData = bm32.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bm32.PixelFormat); 
    Int32 stride = sourceData.Stride; 
    // Copy the image data into a local array so we can use managed functions to manipulate it. 
    Byte[] data = new Byte[stride * height]; 
    Marshal.Copy(sourceData.Scan0, data, 0, data.Length); 
    Byte colR = clearColour.R; 
    Byte colG = clearColour.G; 
    Byte colB = clearColour.B; 
    for (Int32 y = 0; y < height; y++) 
    { 
     Int32 inputOffs = y * stride; 
     for (Int32 x = 0; x < width; x++) 
     { 
      if (data[inputOffs + 2] == colR && data[inputOffs + 1] == colG && data[inputOffs] == colB) 
       data[inputOffs + 3] = 0; 
      inputOffs += 4; 
     } 
    } 
    // Copy the edited image data back. 
    Marshal.Copy(data, 0, sourceData.Scan0, data.Length); 
    bm32.UnlockBits(sourceData); 
    return bm32; 
} 

这可以方便地与一个容差水平,而不是一个确切的匹配得到加强,像Math.Abs(data[inputOffs + 2] - colR) < tolerance ,或者通过将字节实际转换为颜色对象并进行其他类似的近似(如色调/饱和度/亮度)。

相关问题