65.9K
CodeProject 正在变化。 阅读更多。
Home

将纹理应用于位图

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.96/5 (20投票s)

2003年8月31日

viewsIcon

92475

展示如何将纹理应用于位图。

引言

我觉得这段代码可能对某人有用。我基本上是从 VBForums 论坛上的某个帖子(我自己的帖子)复制粘贴过来的。我的做法是:我将纹理转换为灰度。最白的像素(最高的 r、g 或 b 值)将具有最大的透明度。最暗的像素在应用纹理时将具有最小的透明度。

我的代码在技术上可能不正确,或者不是执行此操作的最有效方法。我只是想分享如何应用纹理的想法。希望这有帮助。

详细说明

调用 ApplyTexture() 将纹理应用于您的位图。这是代码

   ' REMEMBER to add this to the class file that contains 
    ' this code: Imports System.Drawing.Imaging

    ' Modifies the ORIGINAL bitmap
    ' textureTransparency  has to be between 0 and 1, 
    ' with 0 being the least transparent, and 1 the most transparent 
    Public Shared Sub ApplyTexture(ByRef bmp As Bitmap, _
           ByVal texture As Bitmap, _
           ByVal textureTransparency As Single)

        If (bmp Is Nothing) OrElse (texture Is Nothing) _
           Then Throw New ArgumentNullException
        If textureTransparency < 0 OrElse textureTransparency > 1 Then
            Throw New ArgumentOutOfRangeException( _
              "textureTransparency must be between 0 and 1.")
        End If

        ' Convert the texture to grayscale before using it
        MakeImageGrayscale(texture)

        Dim x, y, alpha As Integer

        ' Adjust the alpha value of each pixel in the texture bitmap.
        ' The white-most pixels will have the the 
        ' most transparency (highest alpha), 
        ' and the dark-most pixels will have the least transparency.
        For x = 0 To texture.Width - 1
            For y = 0 To texture.Height - 1
                Dim c As Color = texture.GetPixel(x, y)
                ' c.R -> all of the RGB values are the same 
                ' since the image is in grayscale
                alpha = CInt(c.R * textureTransparency)
                c = Color.FromArgb(alpha, c)

                texture.SetPixel(x, y, c)
            Next
        Next

        Dim gr As Graphics = Graphics.FromImage(bmp)
        Dim myBrush As New TextureBrush(texture)

        ' Draw the texture over the original bitmap
        gr.FillRectangle(myBrush, bmp.GetBounds(GraphicsUnit.Pixel))
        myBrush.Dispose()
        gr.Dispose()
    End Sub

    ' Converts the image to grayscale
    Public Shared Sub MakeImageGrayscale(ByVal bmp As Bitmap)
        Dim cMatrix As New ColorMatrix(New Single()() _
            {New Single() {0.299, 0.299, 0.299, 0, 0}, _
            New Single() {0.587, 0.587, 0.587, 0, 0}, _
            New Single() {0.114, 0.114, 0.114, 0, 0}, _
            New Single() {0, 0, 0, 1, 0}, _
            New Single() {0, 0, 0, 0, 1}})

        Dim imageAttrib As New ImageAttributes
        imageAttrib.SetColorMatrix(cMatrix)


        Dim gr As Graphics = Graphics.FromImage(bmp)
        ' Apply the grayscale image attribute
        gr.DrawImage(bmp, New Rectangle(0, 0, bmp.Width, bmp.Height), _
          0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, imageAttrib)
        gr.Dispose()
    End Sub

我不知道如何用 C# 编程,但我设法将其转换为 C# 并使用指针代替 SetPixelGetPixel。我使用了 Christian Graus 在 CodeProject 上的一篇文章来了解如何使用指针读取位图的 RGB 数据,并对其进行了一些修改以读取 ARGB 值。我希望我做的一切都正确:)

这就是它,比 VB 版本更快

// REMEMBER to add this to the class file that contains your code
// using System.Drawing.Imaging;

// Modifies the ORIGINAL bitmap
// textureTransparency  has to be between 0 and 1, 
// with 0 being the least transparent, and 1 the most transparent 
public static void ApplyTexture (Image img, Image texture, 
    float textureTransparency)
{
    if ( (img ==null) || (texture==null) ) 
        throw new ArgumentNullException();
    if (textureTransparency < 0 || textureTransparency > 1) 
        throw new ArgumentOutOfRangeException(
              "Value must be between 0 and 1.");

    // Convert the texture to grayscale before using it
    MakeImageGrayscale (texture);


    Bitmap txtr = new Bitmap(texture);
    BitmapData bmData = txtr.LockBits(new Rectangle(0, 0, 
                 txtr.Width, txtr.Height), 
        ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); 
    int stride = bmData.Stride; 
    System.IntPtr Scan0 = bmData.Scan0; 
    // Adjust the alpha value of each pixel in the texture bitmap.
    // The white-most pixels will have the the 
    // most transparency (highest alpha), 
    // and the dark-most pixels will have the least transparency.
    unsafe
    {
        byte * p = (byte *)(void *)Scan0;
        int nOffset = stride - txtr.Width*4;


        for (int y=0; y < txtr.Height; ++y)
        {
            for (int x=0; x < txtr.Width; ++x)
            {
                // p[3] is alpha  -  array is BGRA (blue, green , 
                // red, alpha)
                p[3] = (byte)(p[0] * textureTransparency);
                p += 4; // Move to the next pixel
            }
            p += nOffset;
        }
    }
    txtr.UnlockBits(bmData);

    Graphics gr = Graphics.FromImage(img);
    TextureBrush myBrush = new TextureBrush(txtr);
    gr.FillRectangle (myBrush,0,0,img.Width, img.Height);
    myBrush.Dispose();
    gr.Dispose();
    txtr.Dispose();
}



// Converts the image to grayscale
public static void MakeImageGrayscale (Image img)
{
    ColorMatrix cMatrix = new ColorMatrix ( 
       new float[][]  { 
         new float[] {0.299F, 0.299F, 0.299F, 0, 0},
         new float[] {0.587F, 0.587F, 0.587F, 0, 0},
         new float[] {0.114F, 0.114F, 0.114F, 0, 0},
         new float[] {0, 0, 0, 1, 0},
         new float[] {0,  0,  0,  1, 0}});

    ImageAttributes imageAttrib = new ImageAttributes();
    imageAttrib.SetColorMatrix(cMatrix);

    Graphics gr = Graphics.FromImage (img);
    // Apply the grayscale image attribute
    gr.DrawImage (img, new Rectangle(0, 0, img.Width, img.Height), 
                    0, 0, img.Width, img.Height, GraphicsUnit.Pixel, 
                    imageAttrib);
    gr.Dispose();
}

感谢 Greg Ingelmo 指正我:)

© . All rights reserved.