/// <summary> /// Share the current sketch as a JPEG with EXIF data /// </summary> /// <param name="parameter">the parameter is not used</param> /// <returns>an async task</returns> protected override async Task ExecuteAsync(object parameter) { var data = App.GetSketchData(); var title = string.IsNullOrWhiteSpace(data.Name) ? "Sketch" : data.Name; var filename = Path.Combine(FileSystem.CacheDirectory, title + ".jpeg"); using (var stream = File.Create(filename)) { InkRenderer.RenderImage(data.Width, data.Height, data.BackgroundColor, data.InkStrokes.ToList(), stream, data.Width); } var photoLibrary = DependencyService.Get <IPhotoLibrary>(); photoLibrary.AddExifData(filename); var request = new ShareFileRequest(title + " #Sketch360", new ShareFile(filename)); await Share.RequestAsync(request).ConfigureAwait(false); var properties = new Dictionary <string, string> { ["width"] = data.Width.ToString(CultureInfo.InvariantCulture), ["inkstrokes"] = data.InkStrokes.Count().ToString(CultureInfo.InvariantCulture), ["background"] = data.BackgroundColor.ToHex(), ["duration"] = data.Duration.TotalMinutes.ToString(CultureInfo.InvariantCulture) }; Analytics.TrackEvent("Share", properties); }
private async Task UpdateWebViewAsync() { var sketchData = App.GetSketchData(); if (sketchData != null) { using (var stream = new MemoryStream()) { InkRenderer.RenderImage( (int)InkCanvas.CanvasSize.Width, (int)InkCanvas.CanvasSize.Height, sketchData.BackgroundColor, sketchData.InkStrokes.ToList(), stream, (int)InkCanvas.CanvasSize.Width); stream.Seek(0, SeekOrigin.Begin); InkCanvas.UpdateImageStream(stream); } //var totalMemory = GC.GetTotalMemory(false); // Collect all generations of memory. GC.Collect(); //System.Diagnostics.Debug.WriteLine("Memory Collected after Rendering ink: {0:N0}", // totalMemory- GC.GetTotalMemory(true)); } var webView = FullPreview;// IsSpanned ? FullPreview : SplitPreview; await webView.UpdateWebViewAsync().ConfigureAwait(false); }
public void TestCreatePathPointsOnePoint() { var builder = new XInkStrokeBuilder(); var inkPoints = new[] { new XInkPoint(new Point(0, 0), 1f, 0f, 0f, 0) }; using var stroke = builder.CreateStrokeFromInkPoints(inkPoints); InkRenderer.CreatePathPoints(stroke); }
/// <summary> /// Export the image in a background task /// </summary> /// <param name="parameter">the parameter is not used</param> /// <returns>an async task</returns> protected override async Task ExecuteAsync(object parameter) { var data = App.GetSketchData(); using var stream = new MemoryStream(); InkRenderer.RenderImage(data.Width, data.Height, data.BackgroundColor, data.InkStrokes.ToList(), stream, data.Width); stream.Seek(0, SeekOrigin.Begin); var array = stream.ToArray(); //https://github.com/Studyxnet/FilePicker-Plugin-for-Xamarin-and-Windows/ var photoLibrary = DependencyService.Get <IPhotoLibrary>(); var now = DateTime.Now; var filename = string.Format( CultureInfo.InvariantCulture, Resources.AppResources.DateFilenameFormat, string.IsNullOrWhiteSpace(data.Name) ? "Sketch360" : data.Name, now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, "jpg"); var chars = Path.GetInvalidFileNameChars(); int index; var filenameChars = filename.ToCharArray(); do { index = filename.IndexOfAny(chars); if (index >= 0) { filenameChars[index] = '_'; filename = new string(filenameChars); } }while (index != -1); var saved = await photoLibrary.SavePhotoAsync(array, string.Empty, filename, Page).ConfigureAwait(false); var properties = new Dictionary <string, string> { ["saved"] = saved.ToString(CultureInfo.InvariantCulture), ["width"] = data.Width.ToString(CultureInfo.InvariantCulture), ["inkstrokes"] = data.InkStrokes.Count().ToString(CultureInfo.InvariantCulture), ["background"] = data.BackgroundColor.ToHex(), ["duration"] = data.Duration.TotalMinutes.ToString(CultureInfo.InvariantCulture) }; Analytics.TrackEvent("Image Exported", properties); }
protected override RawInkSample PipelinedRawToCalibratedConversion(Graphics g, RawInkSample sample, Size clientArea) { sample = base.PipelinedRawToCalibratedConversion(g, sample, clientArea); Point areaVector = new Point(clientArea.Width, clientArea.Height); InkRenderer.PixelToInkSpace(g, ref areaVector); sample.X -= areaVector.X >> 1; sample.Y -= areaVector.Y >> 1; return(sample); }
/// <summary> /// Updates the web view with the current sketch data /// </summary> /// <returns>an async task</returns> public async Task UpdateWebViewAsync() { if (!_navigated) { return; } var sketchData = App.GetSketchData(); if (sketchData == null) { return; } await Task.Run(delegate { var base64 = InkRenderer.RenderImage(sketchData.Width, sketchData.Height, sketchData.InkStrokes, sketchData.BackgroundColor, 1024); var script = $"imageUpdated('{base64}');"; if (Dispatcher == null) { return; } Dispatcher.BeginInvokeOnMainThread(async delegate { try { if (Preview == null) { return; } await Preview.EvaluateJavaScriptAsync(script).ConfigureAwait(false); // There is a limit on the length of strings for the Preview.Eval() method. } catch (Exception e) { var properties = new Dictionary <string, string> { ["ScriptLength"] = script.Length.ToString(CultureInfo.InvariantCulture) }; Crashes.TrackError(e, properties); } }); GC.Collect(); }).ConfigureAwait(false); }
public void TestCreatePathPoints(double x1, double y1, double x2, double y2) { var builder = new XInkStrokeBuilder(); var inkPoints = new[] { new XInkPoint(new Point(x1, y1), 1f, 0f, 0f, 0), new XInkPoint(new Point(x2, y2), 1f, 0f, 0f, 0), }; using var stroke = builder.CreateStrokeFromInkPoints(inkPoints); var points = InkRenderer.CreatePathPoints(stroke); foreach (var item in points) { System.Diagnostics.Debug.WriteLine($"{item.X}, {item.Y}"); } }
private static void AddJpegImage(ISketchData sketchData, ZipOutputStream zipStream) { var jpegEntry = new ZipEntry("sketch.jpeg") { DateTime = DateTime.UtcNow }; zipStream.PutNextEntry(jpegEntry); using var memoryStream = new MemoryStream(); InkRenderer.RenderImage(sketchData.Width, sketchData.Height, sketchData.BackgroundColor, sketchData.InkStrokes.ToList(), memoryStream, sketchData.Width); memoryStream.Seek(0, SeekOrigin.Begin); var buffer = new byte[4096]; StreamUtils.Copy(memoryStream, zipStream, buffer); }
public MainViewModel() { _drawingData = new DrawingData(); _inkRenderer = new InkRenderer(); Scale = new ReactiveProperty <double>(1.0); CanvasWidth = _drawingData.ObserveProperty(x => x.CanvasWidth) .CombineLatest(Scale, (a, b) => a * b) .ToReadOnlyReactiveProperty(); CanvasHeight = _drawingData.ObserveProperty(x => x.CanvasHeight) .CombineLatest(Scale, (a, b) => a * b) .ToReadOnlyReactiveProperty(); ViewportOffsetX = _drawingData.ToReactivePropertyAsSynchronized(x => x.OffsetX, x => x * Scale.Value, x => x / Scale.Value); ViewportOffsetY = _drawingData.ToReactivePropertyAsSynchronized(x => x.OffsetY, x => x * Scale.Value, x => x / Scale.Value); ViewportWidth = _drawingData.ToReactivePropertyAsSynchronized(x => x.ViewWidth, x => x * Scale.Value, x => x / Scale.Value); ViewportHeight = _drawingData.ToReactivePropertyAsSynchronized(x => x.ViewHeight, x => x * Scale.Value, x => x / Scale.Value); MinimapImage = new ReactiveProperty <IRandomAccessStream>(); MinimapViewportScale = _drawingData.ObserveProperty(x => x.CanvasWidth) .CombineLatest(_drawingData.ObserveProperty(x => x.CanvasHeight), ValueTuple.Create) .Select(((double width, double height)x) => { var scaleW = 100 / x.width; var scaleH = 100 / x.height; return(Math.Min(scaleW, scaleH)); }).ToReadOnlyReactiveProperty();
/// <summary> /// Export the image in a background task /// </summary> /// <param name="parameter">the parameter is not used</param> /// <returns>an async task</returns> protected override async Task ExecuteAsync(object parameter) { var data = App.GetSketchData(); using var stream = new MemoryStream(); InkRenderer.RenderImage(data.Width, data.Height, data.BackgroundColor, data.InkStrokes.ToList(), stream, data.Width); stream.Seek(0, SeekOrigin.Begin); var array = stream.ToArray(); //https://github.com/Studyxnet/FilePicker-Plugin-for-Xamarin-and-Windows/ var photoLibrary = DependencyService.Get <IPhotoLibrary>(); var now = DateTime.Now; var filename = string.Format( CultureInfo.InvariantCulture, Resources.AppResources.DateFilenameFormat, string.IsNullOrWhiteSpace(data.Name) ? "Sketch360" : data.Name, now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, "jpg"); var chars = Path.GetInvalidFileNameChars(); int index; var filenameChars = filename.ToCharArray(); do { index = filename.IndexOfAny(chars); if (index >= 0) { filenameChars[index] = '_'; filename = new string(filenameChars); } }while (index != -1); var saved = await photoLibrary.SavePhotoAsync(array, string.Empty, filename, Page).ConfigureAwait(false); var introSketch = "No"; var colors = 0; if (data.InkStrokes.Any()) { var firstStrokeStart = data.InkStrokes.First().StrokeStartTime; if (firstStrokeStart.HasValue && firstStrokeStart.Value.Date == new DateTime(2020, 7, 29)) { // Intro Sketch has 254 strokes and was started on 7/29/2020 if (data.InkStrokes.Count() == 254) { introSketch = "Yes"; } else { introSketch = "Modified"; } } colors = (from inkStroke in data.InkStrokes group inkStroke by inkStroke.DrawingAttributes.Color into c select c.Key).Count(); } var properties = new Dictionary <string, string> { ["saved"] = saved.ToString(CultureInfo.InvariantCulture), ["width"] = data.Width.ToString(CultureInfo.InvariantCulture), ["inkstrokes"] = data.InkStrokes.Count().ToString(CultureInfo.InvariantCulture), ["background"] = data.BackgroundColor.ToHex(), ["durationMin"] = data.Duration.TotalMinutes.ToString(CultureInfo.InvariantCulture), ["introSketch"] = introSketch, ["startDate"] = data.Start.ToString("u", CultureInfo.InvariantCulture), ["colors"] = colors.ToString("g", CultureInfo.InvariantCulture) }; Analytics.TrackEvent("Image Exported", properties); }
public void TestCreatePathPointsEmpty() { using var inkStroke = new XInkStroke(); InkRenderer.CreatePathPoints(inkStroke); }
public void CreatePathPointsNullStroke() { InkRenderer.CreatePathPoints(null); }