【问题标题】:Make all gradients to white to be gradient to transparent使所有渐变为白色以渐变为透明
【发布时间】:2014-09-10 20:44:54
【问题描述】:

我正在尝试获取一个有效的代码来打开现有图像并使其透明。问题是我想要所有可能的颜色,从渐变到白色的渐变到透明。我玩过颜色矩阵但失败了......所以我正在做很多可能完全没有必要的东西。我的解决方案如下。

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

【问题讨论】:

  • 给我们一张前后图怎么样?并告诉我们需要多长时间?
  • SetPixel 非常慢。使用 LockBits 和指针的解决方案将运行速度快一百倍(并且您可以完全摆脱 ColorMatrix)。

标签: transparency gdi+ system.drawing colormatrix


【解决方案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 秒 - 不知道这与您的代码相比是否有任何好处!

【讨论】:

    【解决方案2】:

    这是完全未经测试的代码(我什至不知道它是否正确编译),但它应该让您了解如何尽可能快地完成它(当然不使用 GPU):

    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 );
    }
    

    【讨论】:

      猜你喜欢
      • 2014-09-12
      • 1970-01-01
      • 2016-12-02
      • 1970-01-01
      • 2020-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多