Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Applying a texture to a bitmap

0.00/5 (No votes)
14 Sep 2003 1  
Shows you how to apply a texture to a bitmap.

Introduction

I thought this code might be useful to someone. I'm basically copy-pasting it from some post in VBForums (my own post). Here's what I do: I convert the texture to grayscale. The white-most pixels (highest r, g, or b value) will have the most transparency. The dark-most pixels will be the least transparent pixels when you are applying the texture.

My code may technically not be right, or not the most efficient way to do this. I just wanted to share the idea of how you can apply a texture. Hope this helps.

Details

Call ApplyTexture() to apply a texture to your bitmap. Here's the code:

   ' 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

I don't know how to program in C#, but I managed to convert that to C# and used pointers instead of SetPixel and GetPixel. I used one of Christian Graus's articles on CodeProject to figure out how to use pointers to read the RGB data from a bitmap, and changed that a bit around to be able to read ARGB values. I hope I did everything right :)

Here it is, faster than the VB version:

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

Thanks Greg Ingelmo for correcting me :)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here