5

What's the quickest way to compare 2 BitmapImage objects. One is in the Image Source property, and another I create in code.

I can set the image source with the new bitmap image, but it causes flickering because it keeps setting the same image over and over.

I'd like to only set the image if its pixels are different from the one in Image.Source.

EDIT:

AlbumArt is the Image in the view (following MVVM).

Some code (running in the view code-behind):

Task.Factory.StartNew(() =>
    {
        while (((App)Application.Current).Running)
        {
            Thread.Sleep(1000);

            Application.Current.Dispatcher.Invoke(new Action(() =>
            {
                if ((this.DataContext as AudioViewModel).CurrentDevice != null)
                {
                    if ((((this.DataContext as AudioViewModel).CurrentDevice) as AUDIO).SupportsAlbumArt)
                    {
                        BitmapImage image = new BitmapImage();
                        image.BeginInit();
                        image.UriSource = new Uri((((this.DataContext as AudioViewModel).CurrentDevice) as AUDIO).AlbumArt);
                        image.CacheOption = BitmapCacheOption.None;
                        image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
                        image.EndInit();

                        AlbumArt.Source = image;
                        ...
tshepang
  • 12,111
  • 21
  • 91
  • 136
user1518816
  • 215
  • 3
  • 12
  • 1
    How big is the image? As a general rule, I don't think there is a *fast* way to do pixel-wise comparisons of images. You might be better off using some kind of sentinel value to only change the image if the inputs to the image generator change. – Jason Watkins Mar 21 '13 at 21:14
  • 1
    What exactly are you doing? You might post some code. If you simply replace an Image's Source bitmap by another one with exactly the same bitmap, there shouldn't be any flickering. – Clemens Mar 21 '13 at 21:55
  • 1
    Google; WriteableBitmapEx – Meirion Hughes Mar 21 '13 at 22:31
  • I added some code, so you can see that I am setting the image with whatever album art string the Current Device gives me, each second. I take that string, make it a URI, get a bitmap image from that. I see it flickering whenever it keeps setting the same image. – user1518816 Mar 22 '13 at 12:45
  • Meirion, I looked that up, and while it looks like it would do the trick, we're avoiding using open-source libraries. I appreciate it, though. Jason, good question. The images are pretty small, 320 x 320; sa_ddam213's answer below works with little performance hit. – user1518816 Mar 22 '13 at 13:18
  • Also see http://stackoverflow.com/questions/2031217/what-is-the-fastest-way-i-can-compare-two-equal-size-bitmaps-to-determine-whethe – nawfal Jul 24 '13 at 15:42

1 Answers1

12

You could compare the bytes of the BitmapImage to check if they are equal

Something like:

public static class BitmapImageExtensions
{
    public static bool IsEqual(this BitmapImage image1, BitmapImage image2)
    {
        if (image1 == null || image2 == null)
        {
            return false;
        }
        return image1.ToBytes().SequenceEqual(image2.ToBytes());
    }

    public static byte[] ToBytes(this BitmapImage image)
    {
        byte[] data = new byte[] { };
        if (image != null)
        {
            try
            {
                var encoder = new BmpBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(image));
                using (MemoryStream ms = new MemoryStream())
                {
                    encoder.Save(ms);
                    data = ms.ToArray();
                }
                return data;
            }
            catch (Exception ex)
            {
            }
        }
        return data;
    }
}

Usage:

BitmapImage image1 = ..............
BitmapImage image2 = ................

if (image1.IsEqual(image2))
{
    // same image
}
sa_ddam213
  • 42,848
  • 7
  • 101
  • 110