2014-09-10 10 views
1

기존 이미지를 열고 투명하게 만드는 효율적인 코드를 얻으려고합니다. 것은 가능한 모든 그라디언트가 그라디언트가되도록 그라디언트를 투명하게 만드는 것을 원하는 것입니다. Color Matrix에서 약간 놀았지만 실패했습니다 ... 대신에 나는 불필요한 많은 것들을하고 있습니다. 내 솔루션은 다음과 같습니다.모든 그라디언트를 흰색으로 그라디언트로 만듭니다.

1) 기존 파일을 엽니 다.

2)는 graysscale

4

) 반전 계조 화상으로부터 α, 새로운 이미지 픽셀 당 화소로서 적색 값을 적용 반전 소스

3)로부터 계조로서 새로운 이미지를 만든다. 다른 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

이전 이미지와 이후 이미지는 어떻습니까? 그리고 얼마나 걸리는지 말해 주시겠습니까? –

+0

SetPixel이 놀랍도록 느립니다. LockBits 및 포인터를 사용하는 솔루션은 100 배 빠르게 실행됩니다 (그리고 ColorMatrix를 완전히 제거 할 수 있습니다). –

답변

1

당신은 ImageMagick이 당신을 위해이 일을 얻을 수 system()를 사용할 수 있습니다. 그것은 무료이며 이용 가능합니다 here.

또한 Windows .NET 바인딩을 사용할 수 있습니다. here을 참조하면 system()없이 ImageMagick의 라이브러리 함수를 직접 프로그램에서 호출 할 수 있습니다.

난 당신이 명령 줄에서 다음과 같이 수행 할 수 있습니다 무엇을하려고 생각 :

convert input.bmp \(+clone -colorspace gray \) -alpha off -compose copy_opacity -composite output.png 

내가 이미지 3500x2000에 위의 벤치마킹이 0.8 초 밖에 걸리지 않는다 - 아무 생각도 그 어떤 좋은 경우 귀하의 코드에 비해 또는 아닙니다!

1

이것은 완전히 테스트되지 않은 코드입니다 (올바르게 컴파일 된지도 모르겠지만). GPL을 사용하지 않고 최대한 빨리 수행하는 방법에 대한 아이디어를 제공해야합니다.

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