1

The XAML:

<ImageBrush x:Key="Symbol1Brush" ImageSource="Resources\Symbol1.png" Stretch="Uniform" />

The code:

// In some class
_imageProcessor = new ImageProcessor(Resources["Symbol1Image"] as BitmapImage)

and

public class ImageProcessor
{
    private readonly Bitmap _primaryMarkerSymbol;

    public ImageProcessor(BitmapImage primaryMarkerSymbol)
    {
        if (primaryMarkerSymbol == null)
            throw new ArgumentNullException("primaryMarkerSymbol");

        _primaryMarkerSymbol = new Bitmap(primaryMarkerSymbol.StreamSource);
    }

    public Bitmap ProcessImage()
    {
        Graphics g = Graphics.FromImage(img);
        g.DrawImage(_primaryMarkerSymbol);
        g.Flush();

        return img;
    }
}

_primaryMarkerSymbol = new Bitmap(primaryMarkerSymbol.StreamSource) throws Exception: Value of 'null' is not valid for 'stream'.

I assume the StreamSource is not populated if BitmapImage is created from Resource.

What alternatives there are? Thanks.

EDIT:

The point is to use the source object (ex. ImageBrush, BitmapImage) defined in the XAML ResourceDictionary.

J Pollack
  • 2,788
  • 3
  • 29
  • 43
  • Take a look at the answer by Daniel Wolf to the following question: http://stackoverflow.com/questions/94456/load-a-wpf-bitmapimage-from-a-system-drawing-bitmap/6775114#6775114 – Chris Taylor Mar 07 '12 at 10:06
  • Thank you for the link. It might come in handy in the future. – J Pollack Mar 07 '12 at 16:22

4 Answers4

3

You might need to copy the bitmap's pixels somehow like this:

// test image
BitmapImage image = new BitmapImage(new Uri(@"C:\Users\Public\Pictures\Sample Pictures\Desert.jpg"));

// copy to byte array
int stride = image.PixelWidth * 4;
byte[] buffer = new byte[stride * image.PixelHeight];
image.CopyPixels(buffer, stride, 0);

// create bitmap
System.Drawing.Bitmap bitmap =
    new System.Drawing.Bitmap(
        image.PixelWidth,
        image.PixelHeight,
        System.Drawing.Imaging.PixelFormat.Format32bppArgb);

// lock bitmap data
System.Drawing.Imaging.BitmapData bitmapData =
    bitmap.LockBits(
        new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
        System.Drawing.Imaging.ImageLockMode.WriteOnly,
        bitmap.PixelFormat);

// copy byte array to bitmap data
System.Runtime.InteropServices.Marshal.Copy(
    buffer, 0, bitmapData.Scan0, buffer.Length);

// unlock
bitmap.UnlockBits(bitmapData);
Clemens
  • 123,504
  • 12
  • 155
  • 268
  • Thank you for your reply and code. It is massive! Especially the interop and bit handling. I forgot to add the requirement to use XAML object as the source (not hard coded path), sorry about that. – J Pollack Mar 07 '12 at 09:30
  • The code should work with any BitmapSource, whether from XAML or code doesn't matter. – Clemens Mar 07 '12 at 09:34
1

This worked for me to set an image source using resource files

var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(MyProject.Properties.Resources.myImage.GetHbitmap(),
                                  IntPtr.Zero,
                                  Int32Rect.Empty,
                                  BitmapSizeOptions.FromEmptyOptions());
MyButton.Background = new ImageBrush(bitmapSource);
0

In the constructor, I would rather use this:

System.Windows.Resources.StreamResourceInfo imageInfo = System.Windows.Application.GetResourceStream(primaryMarkerSymbol.UriSource);
_primaryMarkerSymbol = Image.FromStream(imageInfo.Stream);
-1

On a clear moment I have come up with a solution that I could saddle with.

I used the BitmapImage.UriSource to get the relative image path and load the Image:

public class ImageProcessor
{
    private readonly Image _primaryMarkerSymbol;

    public ImageProcessor(BitmapImage primaryMarkerSymbol)
    {
        _primaryMarkerSymbol = Image.FromFile(primaryMarkerSymbol.UriSource.ToString());
    }

    public Bitmap ProcessImage(string fileName)
    {
        var img = new Bitmap(fileName);
        Graphics g = Graphics.FromImage(img);
        g.DrawImage(_primaryMarkerSymbol);
        g.Flush();

        return img;
    }
}

It would be good if I could use the object itself to draw the image on the graphics not to load by path. So you are welcome to come up with a better idea.

J Pollack
  • 2,788
  • 3
  • 29
  • 43
  • Well, if the `UriSource` property is actually set and still valid, that's ok. Then you could also write `new Bitmap(Image.FromFile(...))`. – Clemens Mar 07 '12 at 10:16
  • It is set in the I just did not realise it, at first. – J Pollack Mar 07 '12 at 16:25
  • 1
    Yes, that's true in your specific case. But when neither UriSource nor StreamSource are set, you will still be able to copy pixels. – Clemens Mar 07 '12 at 16:33
  • The one who down voted this answer, could explain what is wrong with it. Better yet, post your own answer. – J Pollack Mar 10 '14 at 08:30
  • I'd like to try to use your soloution, but there are issues with your code. #1) img is never defined. Did you intend to pass it in as arg to ProcessImage()? #2) DrawImage() does not have any method signature that receives only 1 argument as you have here. Please advise. – Taersious Jun 01 '16 at 12:42
  • @Taersious: Please see the edit. Sorry that I forgot to let you know of the update ;) – J Pollack Mar 08 '19 at 15:52