Skip to content

Instantly share code, notes, and snippets.

@SunboX
Created February 7, 2017 11:27
Show Gist options
  • Save SunboX/16381f40afd34aa4d2f31deb9de7ed15 to your computer and use it in GitHub Desktop.
Save SunboX/16381f40afd34aa4d2f31deb9de7ed15 to your computer and use it in GitHub Desktop.
UWP ZXing with preview
using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading;
using System.Threading.Tasks;
using Windows.Graphics.Imaging;
using Windows.Media.Capture;
using Windows.Media.MediaProperties;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Navigation;
using ZXing;
using ZXing.Common;
namespace IoT_WebCam_Test
{
public sealed partial class MainPage : Page
{
// Rotation metadata to apply to the preview stream and recorded videos (MF_MT_VIDEO_ROTATION)
// Reference: http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh868174.aspx
private static readonly Guid RotationKey = new Guid("C380465D-2271-428C-9B83-ECEA3B4A85C1");
private readonly BarcodeReader _reader = new BarcodeReader
{
Options = new DecodingOptions
{
PossibleFormats = new[]
{
BarcodeFormat.QR_CODE,
BarcodeFormat.EAN_13,
BarcodeFormat.EAN_8,
BarcodeFormat.UPC_A,
BarcodeFormat.UPC_E,
BarcodeFormat.UPC_EAN_EXTENSION
},
TryHarder = true
}
};
private bool _isPreviewing;
private bool _isRecording;
private MediaCapture _mediaCapture;
public MainPage()
{
InitializeComponent();
InitCamera();
}
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
Cleanup();
base.OnNavigatedFrom(e);
}
private async void InitCamera()
{
try
{
if (_mediaCapture != null)
{
// Cleanup MediaCapture object
if (_isPreviewing)
{
await _mediaCapture.StopPreviewAsync();
_isPreviewing = false;
}
if (_isRecording)
{
await _mediaCapture.StopRecordAsync();
_isRecording = false;
}
_mediaCapture.Dispose();
_mediaCapture = null;
}
status.Text = "Initializing camera to capture audio and video...";
// Use default initialization
_mediaCapture = new MediaCapture();
await _mediaCapture.InitializeAsync();
// get available resolutions
var resolutions = _mediaCapture.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.Photo).ToList();
for (var i = 0; i < resolutions.Count; i++)
{
var prop = resolutions[i] as VideoEncodingProperties;
if (prop != null)
{
Debug.WriteLine($"Size {i}: {prop.Width}, {prop.Height}");
}
}
/*
_mediaCapture.VideoDeviceController.FocusControl.Configure(new FocusSettings
{
Mode = FocusMode.Auto,
AutoFocusRange = AutoFocusRange.Macro
});
*/
// set used resolution
await _mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.Photo, resolutions[40]);
// Set callbacks for failure and recording limit exceeded
status.Text = "Device successfully initialized for video recording!";
_mediaCapture.Failed += mediaCapture_Failed;
// Start Preview
previewElement.Source = _mediaCapture;
await _mediaCapture.StartPreviewAsync();
var props = _mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview);
//props.Properties.Add(RotationKey, 90);
await _mediaCapture.SetEncodingPropertiesAsync(MediaStreamType.VideoPreview, props, null);
_isPreviewing = true;
status.Text += "Camera preview succeeded";
var cancellationTokenSource = new CancellationTokenSource();
await Task.Factory.StartNew(async () =>
{
for (;;)
{
if (cancellationTokenSource.IsCancellationRequested)
{
break;
}
await TakePhoto();
}
}, cancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
catch (Exception ex)
{
status.Text = "Unable to initialize camera for audio/video mode: " + ex.Message;
status.Visibility = Visibility.Visible;
}
}
private async void Cleanup()
{
if (_mediaCapture != null)
{
// Cleanup MediaCapture object
if (_isPreviewing)
{
await _mediaCapture.StopPreviewAsync();
//playbackElement.Source = null;
_isPreviewing = false;
}
if (_isRecording)
{
await _mediaCapture.StopRecordAsync();
_isRecording = false;
//recordVideo.Content = "Start Video Record";
//recordAudio.Content = "Start Audio Record";
}
_mediaCapture.Dispose();
_mediaCapture = null;
}
}
/// <summary>
/// Callback function for any failures in MediaCapture operations
/// </summary>
/// <param name="currentCaptureObject"></param>
/// <param name="currentFailure"></param>
private async void mediaCapture_Failed(MediaCapture currentCaptureObject,
MediaCaptureFailedEventArgs currentFailure)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
try
{
status.Text = "MediaCaptureFailed: " + currentFailure.Message;
if (!_isRecording)
{
return;
}
await _mediaCapture.StopRecordAsync();
status.Text += "\n Recording Stopped";
}
catch (Exception)
{
// ignored
}
finally
{
status.Text += "\nCheck if camera is diconnected. Try re-launching the app";
}
});
}
private async Task TakePhoto()
{
try
{
//await _mediaCapture.VideoDeviceController.FocusControl.FocusAsync();
var lowLagCapture =
await
_mediaCapture.PrepareLowLagPhotoCaptureAsync(
ImageEncodingProperties.CreateUncompressed(MediaPixelFormat.Bgra8));
var capturedPhoto = await lowLagCapture.CaptureAsync();
var softwareBitmap = capturedPhoto.Frame.SoftwareBitmap;
await lowLagCapture.FinishAsync();
if (softwareBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8 || softwareBitmap.BitmapAlphaMode != BitmapAlphaMode.Ignore)
{
softwareBitmap = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore);
}
var newBmp = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Gray8, BitmapAlphaMode.Ignore);
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
var bytes = EncodedBytes(newBmp);
TestPreview.Source = await SoftwareImageSourceFromBytes(bytes, newBmp.PixelWidth, newBmp.PixelHeight, BitmapPixelFormat.Gray8);
//Debug.WriteLine($"Size: {newBmp.PixelWidth}, {newBmp.PixelHeight}");
//await Task.Delay(300);
var result = _reader.Decode(bytes, newBmp.PixelWidth, newBmp.PixelHeight, RGBLuminanceSource.BitmapFormat.Gray8);
if (result != null)
{
Debug.WriteLine(result.Text);
}
});
}
catch (Exception)
{
// ignored
}
}
[ComImport]
[Guid("5b0d3235-4dba-4d44-865e-8f1d0e4fd04d")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
unsafe interface IMemoryBufferByteAccess
{
void GetBuffer(out byte* buffer, out uint capacity);
}
private byte[] EncodedBytes(SoftwareBitmap soft)
{
using (var buffer = soft.LockBuffer(BitmapBufferAccessMode.ReadWrite))
using (var reference = buffer.CreateReference())
{
unsafe
{
// Get a pointer to the pixel buffer
var data = default(byte*);
uint capacity = 0;
var memoryBufferByteAccess = reference as IMemoryBufferByteAccess;
if (memoryBufferByteAccess != null)
{
memoryBufferByteAccess.GetBuffer(out data, out capacity);
}
var len = checked((int) capacity);
var bytes = new byte[len];
Marshal.Copy((IntPtr)data, bytes, 0, len);
return bytes;
}
}
}
public static async Task<WriteableBitmap> ImageFromBytes(byte[] bytes, int width, int height)
{
var wb = new WriteableBitmap(width, height);
using (var stream = wb.PixelBuffer.AsStream())
{
await stream.WriteAsync(bytes, 0, bytes.Length);
}
return wb;
}
public static async Task<SoftwareBitmapSource> SoftwareImageSourceFromBytes(byte[] bytes, int width, int height, BitmapPixelFormat bitmapPixelFormat)
{
var grayImage = await ImageFromBytes(bytes, width, width);
var grayscaleBitmap = SoftwareBitmap.CreateCopyFromBuffer(grayImage.PixelBuffer, bitmapPixelFormat, width, height);
var uwpSoftwareBitmap = SoftwareBitmap.Convert(grayscaleBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore);
var source = new SoftwareBitmapSource();
await source.SetBitmapAsync(uwpSoftwareBitmap);
return source;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment