Click here to Skip to main content
Click here to Skip to main content
Go to top

Applying a texture to a bitmap

, 14 Sep 2003
Rate this:
Please Sign up or sign in to vote.
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 Smile | :)

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 Smile | :)

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

Share

About the Author

MrPolite

United States United States
No Biography provided

Comments and Discussions

 
GeneralVB.NET kinda slow PinmemberMrPolite11-Sep-03 13:27 
GeneralRe: VB.NET kinda slow PinsussLaMusaraigne8-Jul-04 22:16 
GeneralRe: VB.NET kinda slow Pinmembersyed shujaat hussain24-Apr-07 0:29 
GeneralGreyscale PinsussGreg Ingelmo3-Sep-03 3:28 
GeneralRe: Greyscale PinmemberMrPolite3-Sep-03 17:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140922.1 | Last Updated 15 Sep 2003
Article Copyright 2003 by MrPolite
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid