Wednesday, January 23, 2013

Windows Phone Scanner-Demo

We can use Barcode-sacnning in windows phone devices. for this purpose make a project with the name ScannerDemo and make a class inside the project with the name PhotoCameraLuminanceSource.cs

firstly we need to make a note that we need to import a reference for Silverlight_ZXing_Core.dll, which you can download from net and easly can add to references.

The PhotoCameraLuminanceSource.cs code is given below


using System;
using com.google.zxing;

namespace ScannerDemo
{
    public class PhotoCameraLuminanceSource : LuminanceSource
    {
        public byte[] PreviewBufferY { get; private set; }

        public PhotoCameraLuminanceSource(int width, int height) : base(width, height)
        {      
            PreviewBufferY = new byte[width * height];
        }

        public override sbyte[] Matrix
        {
            get { return (sbyte[])(Array)PreviewBufferY; }
        }

        public override sbyte[] getRow(int y, sbyte[] row)
        {
            if (row == null || row.Length < Width)
            {
                row = new sbyte[Width];
            }

            for (int i = 0; i < Height; i++)
                row[i] = (sbyte)PreviewBufferY[i * Width + y];

            return row;
        }
    }
}


after this we need to make a layout at MainPage.xaml as follows

<phone:PhoneApplicationPage 
    x:Class="ScannerDemo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait">
    
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Rectangle x:Name="_previewRect" 
                   Margin="0" 
                   Height="800" 
                   Width="600" 
                   HorizontalAlignment="Center" 
                   VerticalAlignment="Center">
            <Rectangle.Fill>
                <VideoBrush x:Name="_previewVideo">
                    <VideoBrush.RelativeTransform>
                        <CompositeTransform  
                            x:Name="_previewTransform" CenterX=".5" CenterY=".5" />
                    </VideoBrush.RelativeTransform>
                </VideoBrush>
            </Rectangle.Fill>
        </Rectangle>
        <ListBox Margin="10" x:Name="_matchesList" FontSize="30" FontWeight="ExtraBold" />
    </Grid>
</phone:PhoneApplicationPage>

finally the code for MainPage.xaml.cs is as given below

using System;
using System.Windows.Threading;
using System.Windows.Navigation;
using System.Collections.ObjectModel;

using Microsoft.Devices;
using com.google.zxing;
using com.google.zxing.common;
using com.google.zxing.qrcode;

namespace ScannerDemo
{
    public partial class MainPage
    {
        private readonly DispatcherTimer _timer;
        private readonly ObservableCollection<string> _matches;

        private PhotoCameraLuminanceSource _luminance;
        private QRCodeReader _reader;
        private PhotoCamera _photoCamera;
        
        public MainPage()
        {            
            InitializeComponent();

            _matches = new ObservableCollection<string>();
            _matchesList.ItemsSource = _matches;

            _timer = new DispatcherTimer();
            _timer.Interval = TimeSpan.FromMilliseconds(250);
            _timer.Tick += (o, arg) => ScanPreviewBuffer();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            _photoCamera = new PhotoCamera();
            _photoCamera.Initialized += OnPhotoCameraInitialized;            
            _previewVideo.SetSource(_photoCamera);

            CameraButtons.ShutterKeyHalfPressed += (o, arg) => _photoCamera.Focus();

            base.OnNavigatedTo(e);
        }

        private void OnPhotoCameraInitialized(object sender, CameraOperationCompletedEventArgs e)
        {
            int width = Convert.ToInt32(_photoCamera.PreviewResolution.Width);
            int height = Convert.ToInt32(_photoCamera.PreviewResolution.Height);
            
            _luminance = new PhotoCameraLuminanceSource(width, height);
            _reader = new QRCodeReader();

            Dispatcher.BeginInvoke(() => {
                _previewTransform.Rotation = _photoCamera.Orientation;
                _timer.Start();
            });
        }
 
        private void ScanPreviewBuffer()
        {
            try
            {
                _photoCamera.GetPreviewBufferY(_luminance.PreviewBufferY);
                var binarizer = new HybridBinarizer(_luminance);
                var binBitmap = new BinaryBitmap(binarizer);
                var result = _reader.decode(binBitmap);
                Dispatcher.BeginInvoke(() => DisplayResult(result.Text));
            }
            catch
            {
            }            
        }

        private void DisplayResult(string text)
        {
            if(!_matches.Contains(text))
                _matches.Add(text);            
        }
    }
}

enjoy the barcode simple scanner solution and have a great day with windows phone development.

No comments:

Post a Comment