none
Example usage of BitmapSource.Create RRS feed

  • Question

  • Would it be possible to see an example of using BitmapSource.Create to draw a code generated image in RGBA format? My images are always coming out blank.

    Also, does BitmapSource.Create make a copy of the pixel data when it's called or can I modify the data after the call to change the image?
    Friday, November 18, 2005 10:32 AM

Answers

  • Sure. The simplest example is using a byte[].

                List<System.Windows.Media.Color> colors = new List<System.Windows.Media.Color>();
                colors.Add(System.Windows.Media.Colors.Red);
                colors.Add(System.Windows.Media.Colors.Blue);

                BitmapPalette palette = new BitmapPalette(colors);
                System.Windows.Media.PixelFormat pf =
                    System.Windows.Media.PixelFormats.Indexed1;
                int width = 128;
                int height = width;
                int stride = width/pf.BitsPerPixel;

                byte[] pixels = new byte[height*stride];

                for (int i = 0; i < height*stride; ++i)
                {
                    if (i < height*stride/2)
                    {
                        pixels[ i ] = 0x00;
                    }
                    else
                    {
                        pixels[ i ] = 0xff;
                    }
                }

                BitmapSource image = BitmapSource.Create(
                    width,
                    height,
                    96,
                    96,
                    pf,
                    palette,
                    pixels,
                    stride);

    Please note that the above example uses an Indexed1 PixelFormat. If you would like to create an image that is Bgra32, then your pixels array must contain 4 bytes at a time in blue, green, red, alpha order.

    Robert.

    Wednesday, November 30, 2005 5:38 PM
    Moderator

All replies

  • Sure. The simplest example is using a byte[].

                List<System.Windows.Media.Color> colors = new List<System.Windows.Media.Color>();
                colors.Add(System.Windows.Media.Colors.Red);
                colors.Add(System.Windows.Media.Colors.Blue);

                BitmapPalette palette = new BitmapPalette(colors);
                System.Windows.Media.PixelFormat pf =
                    System.Windows.Media.PixelFormats.Indexed1;
                int width = 128;
                int height = width;
                int stride = width/pf.BitsPerPixel;

                byte[] pixels = new byte[height*stride];

                for (int i = 0; i < height*stride; ++i)
                {
                    if (i < height*stride/2)
                    {
                        pixels[ i ] = 0x00;
                    }
                    else
                    {
                        pixels[ i ] = 0xff;
                    }
                }

                BitmapSource image = BitmapSource.Create(
                    width,
                    height,
                    96,
                    96,
                    pf,
                    palette,
                    pixels,
                    stride);

    Please note that the above example uses an Indexed1 PixelFormat. If you would like to create an image that is Bgra32, then your pixels array must contain 4 bytes at a time in blue, green, red, alpha order.

    Robert.

    Wednesday, November 30, 2005 5:38 PM
    Moderator
  • How can I create a bitmap from 12bit gray image source?  I know that 12bit is not directly supported but for now it would be enough to see something on the screen and I will do the palette manipulation later. The image is 512x512 and contains the 12bit pixel values in an 16bit ushort array.
    The following code throws an ArgumentException without telling me which parameter is meant at the Create method call:


    ushort[] pixels = new ushort[image.Width*image.Height];
    int index = 0;
    for (int y = 0; y < image.Height; y++)
    {
       for (int x = 0; x < image.Width; x++)
       {
          pixels[index] = image[x,y];
          index++;
       }
    }
     
    PixelFormat pixelFormat = PixelFormats.Gray16;
    BitmapPalette palette = BitmapPalettes.Gray16;
    BitmapSource source = BitmapSource.Create(image.Width, image.Height, 96, 96, pixelFormat, palette, pixels, 0);

     


    Thanks,

    Daniel
    Sunday, December 11, 2005 8:34 PM
  • The PixelFormat Gray16 is not palettized. When creating a BitmapSource with this PixelFormat, please use null as the parameter for the Palette.
    Monday, December 12, 2005 6:36 PM
    Moderator
  • Sorry, but it doesn't work either. I tried every combination of parameters that seemed meaningful to me with no luck. I can't even create a BitmapSource with PixelFormats.Bgra32 and an int array or a byte array as source. Any ideas?
    Tuesday, December 13, 2005 12:01 PM
  • I have some questions regarding this example. It seems very strange to allocate 
       height * stride = height * width / pf.BitsPerPixel = height * width / 1
    when Indexed1 is a one-bit format. It would seem to make more sense to use 
       height * width / 8 
    bytes or as a general formula
       height * (width * pf.BitsPerPixel / 8)

    I am specifically puzzled by how stride should be set. When I look up BitmapSource.Create in the .NET Framework 3.5 documentation (http://msdn.microsoft.com/da-dk/library/ms616045(en-us).aspx) stride is described as:
      "The stride of the bitmap",
    which is not any more information than what was allready available in the parameter name.


    Wednesday, June 25, 2008 9:00 AM
  • I've come across this forum thread multiple times while trying to figure out how to created Indexed1 images.  Eventually I just had to go with guess-and-check.  I thought I'd share my findings.

    The API requires the stride of an Indexed1 image to be the same as the width.  However, internally it will only review the first width / 8 bytes of each row of data.  What this means is that 87.5% of the space in the byte buffer is wasted. 

    You can see exactly how to set all the important bytes in the following sample.  Remember that each byte set will set 8 pixels.

    static void Main(string[] args)
    {
      List<System.Windows.Media.Color> colors = new List<System.Windows.Media.Color>();
      colors.Add(System.Windows.Media.Colors.Red);
      colors.Add(System.Windows.Media.Colors.Blue);
    
      System.Windows.Media.Imaging.BitmapPalette palette 
        = new System.Windows.Media.Imaging.BitmapPalette(colors);
      System.Windows.Media.PixelFormat pf = System.Windows.Media.PixelFormats.Indexed1;
      int width = 16;
      int height = width;
      int stride = width/pf.BitsPerPixel;
    
      byte[] pixels = new byte[height*stride];
      //Note that pixels is filled with zeroes to start.
      //If we miss a data area, it will show up as a red spot on the image.
    
      //Fill all the pertinent data areas with blue.
      for (int y = 0; y < width; ++y)
      {
        for (int x = 0; x < width / 8; ++x)
        {
          int index = (y * stride) + x;
          pixels[index] = 0xff;
        }
      }
    
      using (FileStream file = new FileStream("test.bmp", FileMode.Create, FileAccess.ReadWrite))
      {
        System.Windows.Media.Imaging.BmpBitmapEncoder encoder 
          = new System.Windows.Media.Imaging.BmpBitmapEncoder();
        encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(
          System.Windows.Media.Imaging.BitmapSource.Create(width, height, 96.0, 96.0,
          System.Windows.Media.PixelFormats.Indexed1, palette, pixels, stride)));
        encoder.Save(file);
      }
    
      System.Diagnostics.Process.Start("test.bmp");
    }
    

    Wednesday, April 20, 2011 11:54 PM
  • Suppose the code were changed to black and white as the following modifications show:

    List<System.Windows.Media.Color> colors = new List<System.Windows.Media.Color>(); colors.Add(System.Windows.Media.Colors.Black); colors.Add(System.Windows.Media.Colors.White); BitmapPalette myPalette = new BitmapPalette(colors)

    BitmapSource image = BitmapSource.Create(
                    width,
                    height,
                    96,
                    96,
                    PixelFormats.BlackWhite,
                    myPalette, 
                    pixels, 
                    stride);

    This results in a BitmapSource with a null palette. Is that normal? My general
    problem is that my image code occasionally creates a TIF file with an inverted
    image. I am trying to determine what factor(s) determine(s) the resulting
    display. I have code to invert the byte array and it usually works. I also
    have code to count 1 and 0 bits in the array. I always want a 'black ink on
    white paper' image so there should always be more 'white' than 'black' bits.
    But I am unable to work out the magic incantation for being able to predict
    when I need to invert the byte array (and thus, usually, image). And I sure
    don't understand why inverting the byte array doesn't ALWAYS work to invert the
    image.


    • Edited by cascad Tuesday, February 12, 2013 7:58 PM formatting lines
    Tuesday, February 12, 2013 7:55 PM