public async Task<OpticalReaderLib.EnhanceResult> EnhanceAsync(OpticalReaderLib.Frame frame)
        {
            if (frame.Format == OpticalReaderLib.FrameFormat.Gray8)
            {
                _threshold = _threshold + _jump;

                if (_threshold > _max)
                {
                    _threshold = _min;
                }

                var f = await Task.Run<OpticalReaderLib.Frame>(() =>
                {
                    for (int i = 0; i < frame.Buffer.Length; i++)
                    {
                        frame.Buffer[i] = (byte)(frame.Buffer[i] < _threshold ? 0x00 : 0xff);
                    }

                    return frame;
                });

                return new OpticalReaderLib.EnhanceResult()
                {
                    Frame = f
                };
            }
            else
            {
                throw new Exception("Dumb little custom enhancer only supports Gray8 encoded frames");
            }
        }
        private async Task<Tuple<ProcessResult, WriteableBitmap>> ProcessFrameAsync(OpticalReaderLib.Frame frame)
        {
            //System.Diagnostics.Debug.WriteLine("Start processing");
            
            var rectSize = new Windows.Foundation.Size(
                ReaderBorder.ActualWidth / Canvas.ActualWidth * frame.Dimensions.Width / _zoom,
                ReaderBorder.ActualHeight / Canvas.ActualHeight * frame.Dimensions.Height / _zoom);

            var rectOrigin = new Windows.Foundation.Point(
                frame.Dimensions.Width / 2 - rectSize.Width / 2,
                frame.Dimensions.Height / 2 - rectSize.Height / 2);

            var area = new Windows.Foundation.Rect(rectOrigin, rectSize);

            ProcessResult result = null;

            try
            {
                result = await OpticalReaderTask.Instance.Processor.ProcessAsync(frame, area, _rotation);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(String.Format("Processing frame failed: {0}\n{1}", ex.Message, ex.StackTrace));
            }

            //System.Diagnostics.Debug.WriteLine("Stop processing");

            InterestAreaPolygon.Points = null;

            if (result != null)
            {
                _lastSuccess = DateTime.Now;

                var thumbnail = GenerateThumbnail();

                var interestPointCollection = new PointCollection();

                foreach (var point in result.InterestPoints)
                {
                    interestPointCollection.Add(new System.Windows.Point(point.X, point.Y));
                }

                InterestAreaPolygon.Points = interestPointCollection;

                return new Tuple<ProcessResult, WriteableBitmap>(result, thumbnail);
            }
            else
            {
                var sinceLastSuccess = DateTime.Now - _lastSuccess;

                if (sinceLastSuccess > OpticalReaderTask.Instance.FocusInterval)
                {
                    try
                    {
                        var status = await _device.FocusAsync();

                        _lastSuccess = DateTime.Now;

                        // todo use camera focus lock status
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine(String.Format("Focusing camera failed: {0}\n{1}", ex.Message, ex.StackTrace));
                    }
                }

                return null;
            }
        }
 private void OpticalReaderTask_Completed(object sender, OpticalReaderLib.OpticalReaderResult e)
 {
     _taskResult = e;
 }