1

I am working on a project where I want to be able to display a QR Code on the screen to the user.

I'm using the QR Code generate from http://qrcodenet.codeplex.com/ which is working fine but I've only found a way to write the QR Code to a file which is now what I want.

Instead, I want the image to be displayed in a control on the WPF window but I don't want to create the file and then set the source of the image to an image control of the newly created file. This seems like a bit of overkill so I'm hoping there is way I can put the stream straight into an image control instead of into a file.

Below is the code that I have so far.

private void generateQRCode()
        {
            QrEncoder encoder = new QrEncoder(ErrorCorrectionLevel.M);
            QrCode qrCode;
            encoder.TryEncode("Test", out qrCode);

            DrawingBrushRenderer dRenderer = new DrawingBrushRenderer(
                new FixedModuleSize(2, QuietZoneModules.Two), System.Windows.Media.Brushes.Black, 
                    System.Windows.Media.Brushes.White);

            DrawingBrush dBrush = dRenderer.DrawBrush(qrCode.Matrix);
            System.Windows.Shapes.Rectangle rect = new System.Windows.Shapes.Rectangle();
            rect.Width = 150;
            rect.Height = 150;
            rect.Fill = dBrush;

            MemoryStream ms = new MemoryStream();
            dRenderer.WriteToStream(qrCode.Matrix, ImageFormatEnum.PNG, ms, new System.Windows.Point(96, 96));

            var image = new System.Drawing.Bitmap(System.Drawing.Image.FromStream(ms), new System.Drawing.Size(new System.Drawing.Point(200, 200)));

            image.Save("myImage.png", System.Drawing.Imaging.ImageFormat.Png);
               
        }

Basically, I want to replace the image.save() function so that the image is instead show directly in a control on my apps GUI, not written to a separate file.

halfer
  • 19,824
  • 17
  • 99
  • 186
Boardy
  • 35,417
  • 104
  • 256
  • 447
  • Not sure about WPF, but I know in WinForms, there is a PictureBox control where you can just set the .Image property of the picture box to your raw image bytes. – Icemanind Jul 15 '14 at 22:04

3 Answers3

3

I've actually never written anything in WPF, so this could be wrong, but you probably want to do something like this. I'll copy the answer from that question below:

using(MemoryStream memory = new MemoryStream())
{
    image.Save(memory, ImageFormat.Png);
    memory.Position = 0;
    BitmapImage bitmapImage = new BitmapImage();
    bitmapImage.BeginInit();
    bitmapImage.StreamSource = memory;
    bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
    bitmapImage.EndInit();
}

Then, I assume, you can associate that BitmapImage with whatever control you use to display the image.

Community
  • 1
  • 1
Matthew Haugen
  • 12,916
  • 5
  • 38
  • 54
1

You can find the answer to this here: Using Image control in WPF to display System.Drawing.Bitmap

HBipmaps from System.Drawing can not be used directly in WPF. Lars Truijens on his post goes to explain but see the snipped of the post below:

According to http://khason.net/blog/how-to-use-systemdrawingbitmap-hbitmap-in-wpf/

   [DllImport("gdi32")]
   static extern int DeleteObject(IntPtr o);

   public static BitmapSource loadBitmap(System.Drawing.Bitmap source)
   {
       IntPtr ip = source.GetHbitmap();
       BitmapSource bs = null;
       try
       {
           bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(ip, 
              IntPtr.Zero, Int32Rect.Empty, 
              System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
       }
       finally
       {
           DeleteObject(ip);
       }

       return bs;
   }

It gets System.Drawing.Bitmap (from WindowsBased) and converts it into BitmapSource, which can be actually used as image source for your Image control in WPF.

image1.Source = YourUtilClass.loadBitmap(SomeBitmap);
Community
  • 1
  • 1
dmportella
  • 4,614
  • 1
  • 27
  • 44
0

With package QrCode.Net (Install-Package QrCode.Net) we can generate the matrix data of qrcode content, so I have make a WPF control with the matrix data.

QRCode.xaml

<UserControl x:Class="WpfApp1.QRCode"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:WpfApp1"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
    <ItemsPanelTemplate x:Key="HorizontalPanel">
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"/>
    </ItemsPanelTemplate>
    <DataTemplate x:Key="PointTemplate">
        <Rectangle Fill="{Binding Color}" Width="{Binding Size, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" Height="{Binding Size, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
    </DataTemplate>
    <DataTemplate x:Key="LineTemplate">
        <ItemsControl ItemsSource="{Binding}" ItemsPanel="{StaticResource HorizontalPanel}" ItemTemplate="{StaticResource PointTemplate}">
        </ItemsControl>
    </DataTemplate>
</UserControl.Resources>
<Grid>
    <ItemsControl Name="qrcodeControl" HorizontalAlignment="Center" VerticalAlignment="Center"
                ItemTemplate="{StaticResource LineTemplate}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel></StackPanel>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
</Grid>

QRCode.xaml.cs

using Gma.QrCodeNet.Encoding;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp1
{
    /// <summary>
    /// Interaction logic for QRCode.xaml
    /// </summary>
    public partial class QRCode : UserControl, INotifyPropertyChanged
    {
        public QRCode()
        {
            InitializeComponent();

            //default point size
            this.Size = 3;
            qrcodeControl.ItemsSource = QRMatrix;
        }

        private ObservableCollection<ObservableCollection<QrCodePoint>> qrMatrix = new ObservableCollection<ObservableCollection<QrCodePoint>>();
        ObservableCollection<ObservableCollection<QrCodePoint>> QRMatrix
        {
            get
            {
                return this.qrMatrix;
            }
        }

        public new static readonly DependencyProperty ContentProperty = DependencyProperty.Register(
            "Content",
            typeof(string),
            typeof(QRCode),
            new UIPropertyMetadata((s, e) =>
            {
                QRCode dp = s as QRCode;
                dp.QRMatrix.Clear();
                dp.Generate(e.NewValue.ToString()).ForEach(
                    line =>
                    {
                        ObservableCollection<QrCodePoint> linePoints = new ObservableCollection<QrCodePoint>();
                        dp.qrMatrix.Add(linePoints);
                        foreach (var point in line)
                        {
                            linePoints.Add(point);
                        }
                    });
                dp.RaisePropertyChanged("Content");
            }));

        public new string Content
        {
            get { return (string)GetValue(ContentProperty); }
            set { SetValue(ContentProperty, value); }
        }

        public static readonly DependencyProperty SizeProperty = DependencyProperty.Register(
            "Size",
            typeof(double),
            typeof(QRCode),
            new UIPropertyMetadata((s, e) =>
            {
                QRCode dp = s as QRCode;
                dp.RaisePropertyChanged("Size");
            }));

        public double Size
        {
            get { return (double)GetValue(SizeProperty); }
            set { SetValue(SizeProperty, value); }
        }

        public List<QrCodePoint[]> Generate(string content)
        {
            List<QrCodePoint[]> result = new List<QrCodePoint[]>();
            QrEncoder encoder = new QrEncoder(ErrorCorrectionLevel.M);
            QrCode qrCode;
            encoder.TryEncode(content, out qrCode);

            for (int i = 0; i < qrCode.Matrix.Height; i++)
            {
                var line = new QrCodePoint[qrCode.Matrix.Width];
                result.Add(line);
                for (int j = 0; j < qrCode.Matrix.Width; j++)
                {
                    line[j] = new QrCodePoint() { Color = qrCode.Matrix[i, j] ? Brushes.Black : Brushes.White };
                }
            }

            return result;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

    public class QrCodePoint
    {
        public SolidColorBrush Color { get; set; }
    }
}

and the MainWindow to use this WPF control

<Window x:Class="WpfApp1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApp1"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Grid>
    <local:QRCode Grid.Column="1" Size="5" Content="Hello, world!"></local:QRCode>
</Grid>

Phoeson
  • 191
  • 1
  • 6