我试图获得一个打开现有图像并使其透明的高效代码。问题是,我希望所有可能的颜色都是渐变到白色的渐变到透明。我已经和Color Matrix玩了一下但是失败了......所以我做了很多可能完全不必要的东西。我的解决方案如下。
1)打开现有文件。
2)从源
创建一个灰度的新图像3)反转灰度
4)将红色值应用于反转灰度图像中的alpha,每像素一个像素到新图像。其他RGB值将从原始文件中释放出来。 (对不起我的草率功能......只需要做一个快速测试,看看是否可能)
这在某种程度上很好用,除了处理更大的图像(大约3500x2000像素)需要很多时间它是否可以用ColorMatrix直接执行此操作以跳过每像素进程的像素?还是有其他方法吗?我一直在考虑屏蔽等,但没有任何经验。
由于使用灰度作为输入,当前代码也会使其他颜色比黑色略微透明(不太强烈)。
'VB.NET
Imports System.Drawing
Imports System.Drawing.Imaging
Module Module1
Sub Main()
Dim args() As String = Environment.GetCommandLineArgs
Dim Path As String = String.Empty
If args.Count = 2 Then
Path = args(1)
End If
Try
Dim image1 As Bitmap = CType(Image.FromFile(Path, True), Bitmap)
Dim image2 As New Bitmap(image1.Width, image1.Height)
Dim g As Graphics = Graphics.FromImage(image2)
Dim myColorMatrix As New ColorMatrix
Dim invColor As New ColorMatrix
Dim imageAttr As New ImageAttributes
myColorMatrix.Matrix00 = 0.3F
myColorMatrix.Matrix01 = 0.3F
myColorMatrix.Matrix02 = 0.3F
myColorMatrix.Matrix10 = 0.59F
myColorMatrix.Matrix11 = 0.59F
myColorMatrix.Matrix12 = 0.59F
myColorMatrix.Matrix20 = 0.11F
myColorMatrix.Matrix21 = 0.11F
myColorMatrix.Matrix22 = 0.11F
myColorMatrix.Matrix33 = 1.0
myColorMatrix.Matrix44 = 1.0
imageAttr.SetColorMatrix(myColorMatrix, ColorAdjustType.Default, ColorAdjustType.Default)
g.DrawImage(image1, New Rectangle(0, 0, image1.Width, image1.Height), 0, 0, image1.Width, image1.Height, GraphicsUnit.Pixel, imageAttr)
invColor.Matrix00 = -1
invColor.Matrix11 = -1
invColor.Matrix22 = -1
invColor.Matrix33 = 1
invColor.Matrix44 = 1
invColor.Matrix40 = 1
invColor.Matrix41 = 1
invColor.Matrix42 = 1
imageAttr.SetColorMatrix(invColor, ColorAdjustType.Default, ColorAdjustType.Default)
g.DrawImage(image2, New Rectangle(0, 0, image1.Width, image1.Height), 0, 0, image1.Width, image1.Height, GraphicsUnit.Pixel, imageAttr)
Dim myColor As New Color
Dim x As Integer = 0
Dim y As Integer = 0
Dim myAlpha As Integer = 0
Dim orgColor(2) As Integer
Do Until y = image1.Height
Do Until x = image1.Width
'Get alpha
myAlpha = toRGB(image2.GetPixel(x, y))
orgColor = currentRGB(image1.GetPixel(x, y))
myColor = Color.FromArgb(myAlpha, orgColor(0), orgColor(1), orgColor(2))
image2.SetPixel(x, y, myColor)
x = x + 1
Loop
x = 0
y = y + 1
Loop
image2.Save("C:\test\transparent.png", ImageFormat.Png)
image1.Dispose()
image2.Dispose()
g.Dispose()
Catch ex As System.IO.FileNotFoundException
MsgBox(ex.ToString & vbNewLine & " There was an error opening the bitmap." _
& "Please check the path.")
End Try
End Sub
Private Function toRGB(ByVal Color As Color) As Integer
Dim r As Integer
r = Color.R
Return r
End Function
Private Function currentRGB(ByRef color As Color) As Array
Dim currRGB(2) As Integer
currRGB(0) = color.R
currRGB(1) = color.G
currRGB(2) = color.B
Return currRGB
End Function
End Module
答案 0 :(得分:1)
您可以使用system()
让ImageMagick为您执行此操作。它是免费的here。
它还提供Windows .NET绑定 - 请参阅here,这样您就可以直接从程序中调用ImageMagick的库函数,而无需system()
。
我认为您尝试做的事情可以在命令行中完成:
convert input.bmp \( +clone -colorspace gray \) -alpha off -compose copy_opacity -composite output.png
我在图像3500x2000上对上面进行了基准测试,需要0.8秒 - 不知道与你的代码相比是否有任何好处!
答案 1 :(得分:1)
这是完全未经测试的代码(我甚至不知道它是否正确编译),但它应该让你知道如何尽可能快地完成它(当然不使用GPU):< / p>
public static void AlphaGray(
Bitmap bmp,
int threshold )
{
Rectangle r = new Rectangle( Point.Empty, bmp.Size );
BitmapData bd = bmp.LockBits( r, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb );
unsafe
{
byte* p = (byte*)bd.Scan0.ToPointer();
for ( int i = r.Height * r.Width; i > 0; i--, p +=4 )
{
var avg = (p[0] + p[1] + p[2]) /3;
var bx = p[0] - avg;
var gx = p[1] - avg;
var rx = p[2] - avg;
if( bx*bx + gx*gx + rx*rx < threshold )
p[3] = (byte)avg;
}
}
bmp.UnlockBits( bd );
}