diff --git a/ElectronNET.API/Clipboard.cs b/ElectronNET.API/Clipboard.cs index c49dc95..a43a86b 100644 --- a/ElectronNET.API/Clipboard.cs +++ b/ElectronNET.API/Clipboard.cs @@ -4,6 +4,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; using System.Threading.Tasks; +using Console = System.Console; namespace ElectronNET.API { @@ -251,10 +252,7 @@ namespace ElectronNET.API { BridgeConnector.Socket.Off("clipboard-readImage-Completed"); - var b64 = image.ToString(); - var bytes = Convert.FromBase64String(b64); - - var nativeImage = NativeImage.CreateFromBuffer(bytes); + var nativeImage = ((JObject)image).ToObject(); taskCompletionSource.SetResult(nativeImage); @@ -272,7 +270,7 @@ namespace ElectronNET.API /// public void WriteImage(NativeImage image, string type = "") { - BridgeConnector.Socket.Emit("clipboard-writeImage", JsonConvert.SerializeObject(image.GetBytes()), type); + BridgeConnector.Socket.Emit("clipboard-writeImage", JsonConvert.SerializeObject(image), type); } private JsonSerializer _jsonSerializer = new JsonSerializer() diff --git a/ElectronNET.API/Entities/AddRepresentationOptions.cs b/ElectronNET.API/Entities/AddRepresentationOptions.cs index 0bcd4e3..c5d5bb7 100644 --- a/ElectronNET.API/Entities/AddRepresentationOptions.cs +++ b/ElectronNET.API/Entities/AddRepresentationOptions.cs @@ -4,7 +4,7 @@ namespace ElectronNET.API.Entities { public int? Width { get; set; } public int? Height { get; set; } - public int ScaleFactor { get; set; } + public float ScaleFactor { get; set; } = 1.0f; public byte[] Buffer { get; set; } public string DataUrl { get; set; } } diff --git a/ElectronNET.API/Entities/BitmapOptions.cs b/ElectronNET.API/Entities/BitmapOptions.cs index b965ab0..de5945d 100644 --- a/ElectronNET.API/Entities/BitmapOptions.cs +++ b/ElectronNET.API/Entities/BitmapOptions.cs @@ -6,6 +6,6 @@ namespace ElectronNET.API.Entities { public class BitmapOptions { - public double ScaleFactor { get; set; } = 1.0d; + public float ScaleFactor { get; set; } = 1.0f; } } diff --git a/ElectronNET.API/Entities/CreateFromBitmapOptions.cs b/ElectronNET.API/Entities/CreateFromBitmapOptions.cs new file mode 100644 index 0000000..6b0424a --- /dev/null +++ b/ElectronNET.API/Entities/CreateFromBitmapOptions.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ElectronNET.API.Entities +{ + public class CreateFromBitmapOptions + { + public int? Width { get; set; } + public int? Height { get; set; } + public float ScaleFactor { get; set; } = 1.0f; + } +} diff --git a/ElectronNET.API/Entities/CreateFromBufferOptions.cs b/ElectronNET.API/Entities/CreateFromBufferOptions.cs index b54a9b7..d50b636 100644 --- a/ElectronNET.API/Entities/CreateFromBufferOptions.cs +++ b/ElectronNET.API/Entities/CreateFromBufferOptions.cs @@ -2,8 +2,8 @@ namespace ElectronNET.API.Entities { public class CreateFromBufferOptions { - public int Width { get; set; } - public int Height { get; set; } - public int ScaleFactor { get; set; } + public int? Width { get; set; } + public int? Height { get; set; } + public float ScaleFactor { get; set; } = 1.0f; } } \ No newline at end of file diff --git a/ElectronNET.API/Entities/NativeImage.cs b/ElectronNET.API/Entities/NativeImage.cs index 095cdaf..d6b4f36 100644 --- a/ElectronNET.API/Entities/NativeImage.cs +++ b/ElectronNET.API/Entities/NativeImage.cs @@ -1,139 +1,265 @@ using System; +using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Text.RegularExpressions; +using Newtonsoft.Json; namespace ElectronNET.API.Entities { /// - /// + /// Native Image handler for Electron.NET /// + [JsonConverter(typeof(NativeImageJsonConverter))] public class NativeImage { - private Image _image; - private bool _isTemplateImage = false; + private readonly Dictionary _images = new Dictionary(); + private bool _isTemplateImage; + private static readonly Dictionary ScaleFactorPairs = new Dictionary + { + {"@2x", 2.0f}, {"@3x", 3.0f}, {"@1x", 1.0f}, {"@4x", 4.0f}, + {"@5x", 5.0f}, {"@1.25x", 1.25f}, {"@1.33x", 1.33f}, {"@1.4x", 1.4f}, + {"@1.5x", 1.5f}, {"@1.8x", 1.8f}, {"@2.5x", 2.5f} + }; + + private static float? ExtractDpiFromFilePath(string filePath) + { + var withoutExtension = Path.GetFileNameWithoutExtension(filePath); + return ScaleFactorPairs + .Where(p => withoutExtension.EndsWith(p.Key)) + .Select(p => p.Value) + .FirstOrDefault(); + } + private static Image BytesToImage(byte[] bytes) + { + var ms = new MemoryStream(bytes); + return Image.FromStream(ms); + } + + /// + /// Creates an empty NativeImage + /// public static NativeImage CreateEmpty() { return new NativeImage(); } - public static NativeImage CreateFromBuffer(byte[] buffer) + /// + /// + /// + public static NativeImage CreateFromBitmap(Bitmap bitmap, CreateFromBitmapOptions options = null) { - return new NativeImage(buffer); + if (options is null) + { + options = new CreateFromBitmapOptions(); + } + + return new NativeImage(bitmap, options.ScaleFactor); } - public static NativeImage CreateFromBuffer(byte[] buffer, CreateFromBufferOptions options) + /// + /// Creates a NativeImage from a byte array. + /// + public static NativeImage CreateFromBuffer(byte[] buffer, CreateFromBufferOptions options = null) { - return new NativeImage(buffer); + if (options is null) + { + options = new CreateFromBufferOptions(); + } + + var ms = new MemoryStream(buffer); + var image = Image.FromStream(ms); + + return new NativeImage(image, options.ScaleFactor); } + /// + /// Creates a NativeImage from a base64 encoded data URL. + /// + /// A data URL with a base64 encoded image. public static NativeImage CreateFromDataURL(string dataUrl) { + var images = new Dictionary(); var parsedDataUrl = Regex.Match(dataUrl, @"data:image/(?.+?),(?.+)"); var actualData = parsedDataUrl.Groups["data"].Value; - var type = parsedDataUrl.Groups["type"].Value; var binData = Convert.FromBase64String(actualData); - var imageFormat = type switch - { - "jpeg" => ImageFormat.Jpeg, - "jpg" => ImageFormat.Jpeg, - "png" => ImageFormat.Png, - "gif" => ImageFormat.Gif, - "x-icon" => ImageFormat.Icon, - "bmp" => ImageFormat.Bmp, - _ => ImageFormat.Png - }; + var image = BytesToImage(binData); - return new NativeImage(binData, imageFormat); + images.Add(1.0f, image); + + return new NativeImage(images); } + /// + /// Creates a NativeImage from an image on the disk. + /// + /// The path of the image public static NativeImage CreateFromPath(string path) { - return new NativeImage(path); + var images = new Dictionary(); + if (Regex.IsMatch(path, "(@.+?x)")) + { + var dpi = ExtractDpiFromFilePath(path); + if (dpi == null) + { + throw new Exception($"Invalid scaling factor for '{path}'."); + } + + images[dpi.Value] = Image.FromFile(path); + } + else + { + var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path); + var extension = Path.GetExtension(path); + // Load as 1x dpi + images[1.0f] = Image.FromFile(path); + + foreach (var scale in ScaleFactorPairs) + { + var fileName = $"{fileNameWithoutExtension}{scale}.{extension}"; + if (File.Exists(fileName)) + { + var dpi = ExtractDpiFromFilePath(fileName); + if (dpi != null) + { + images[dpi.Value] = Image.FromFile(fileName); + } + } + } + } + + return new NativeImage(images); } + /// + /// Creates an empty NativeImage + /// public NativeImage() { } - public NativeImage(Bitmap bitmap) + /// + /// Creates a NativeImage from a bitmap and scale factor + /// + public NativeImage(Image bitmap, float scaleFactor = 1.0f) { - _image = bitmap; - } - public NativeImage(string path) - { - _image = Image.FromFile(path); + _images.Add(scaleFactor, bitmap); } - - public NativeImage(byte[] buffer) + /// + /// Creates a NativeImage from a dictionary of scales and images. + /// + public NativeImage(Dictionary imageDictionary) { - var ms = new MemoryStream(buffer); - _image = Image.FromStream(ms); - } - - public NativeImage(byte[] buffer, ImageFormat imageFormat) - { - _image = BytesToImage(buffer, imageFormat); - } - - public Image GetBitmap() - { - return _image; + _images = imageDictionary; } + /// + /// Crops the image specified by the input rectangle and computes scale factor + /// public NativeImage Crop(Rectangle rect) { - using (var g = Graphics.FromImage(_image)) + var images = new Dictionary(); + foreach (var image in _images) { - var bmp = new Bitmap(rect.Width, rect.Height); - g.DrawImage(bmp, new System.Drawing.Rectangle(0, 0, _image.Width, _image.Height), new System.Drawing.Rectangle(rect.X, rect.Y, rect.Width, rect.Height), GraphicsUnit.Pixel); - - return new NativeImage(bmp); + images.Add(image.Key, Crop(rect.X, rect.Y, rect.Width, rect.Height, image.Key)); } + + return new NativeImage(images); } + + /// + /// Resizes the image and computes scale factor + /// + public NativeImage Resize(ResizeOptions options) + { + var images = new Dictionary(); + foreach (var image in _images) + { + images.Add(image.Key, Resize(options.Width, options.Height, image.Key)); + } + + return new NativeImage(images); + } + + /// + /// Add an image representation for a specific scale factor. + /// + /// public void AddRepresentation(AddRepresentationOptions options) { if (options.Buffer.Length > 0) { - _image = CreateFromBuffer(options.Buffer).GetBitmap(); + _images[options.ScaleFactor] = + CreateFromBuffer(options.Buffer, new CreateFromBufferOptions {ScaleFactor = options.ScaleFactor}) + .GetScale(options.ScaleFactor); } else if (!string.IsNullOrEmpty(options.DataUrl)) { - _image = CreateFromDataURL(options.DataUrl).GetBitmap(); + _images[options.ScaleFactor] = CreateFromDataURL(options.DataUrl).GetScale(options.ScaleFactor); } } - public double GetAspectRatio => _image.Width / _image.Height; + /// + /// Gets the aspect ratio for the image based on scale factor + /// + /// Optional + public float GetAspectRatio(float scaleFactor = 1.0f) + { + var image = GetScale(scaleFactor); + if (image != null) + { + return image.Width / image.Height; + } + return 0f; + } + /// + /// Returns a byte array that contains the image's raw bitmap pixel data. + /// public byte[] GetBitmap(BitmapOptions options) { - return ImageToBytes(_image.RawFormat); + return ToBitmap(new ToBitmapOptions{ ScaleFactor = options.ScaleFactor }); } + /// + /// Returns a byte array that contains the image's raw bitmap pixel data. + /// public byte[] GetNativeHandle() { - return ImageToBytes(_image.RawFormat); + return ToBitmap(new ToBitmapOptions()); } - public Size GetSize() + /// + /// Gets the size of the specified image based on scale factor + /// + public Size GetSize(float scaleFactor = 1.0f) { - return new Size + if (_images.ContainsKey(scaleFactor)) { - Width = _image.Width, - Height = _image.Height - }; + var image = _images[scaleFactor]; + return new Size + { + Width = image.Width, + Height = image.Height + }; + } + + return null; } + /// + /// Checks to see if the NativeImage instance is empty. + /// public bool IsEmpty() { - return _image == null; + return _images.Count <= 0; } /// @@ -150,78 +276,102 @@ namespace ElectronNET.API.Entities _isTemplateImage = option; } - - public NativeImage Resize(ResizeOptions options) - { - return new NativeImage((Bitmap)Resize(options.Width, options.Height)); - } - + /// + /// Outputs a bitmap based on the scale factor + /// public byte[] ToBitmap(ToBitmapOptions options) { - return ImageToBytes(_image.RawFormat); + return ImageToBytes(ImageFormat.Bmp, options.ScaleFactor); } + /// + /// Outputs a data URL based on the scale factor + /// public string ToDataURL(ToDataUrlOptions options) { - var mimeType = ImageCodecInfo.GetImageEncoders().FirstOrDefault(x => x.FormatID == _image.RawFormat.Guid)?.MimeType; + if (!_images.ContainsKey(options.ScaleFactor)) + { + return null; + } + + var image = _images[options.ScaleFactor]; + var mimeType = ImageCodecInfo.GetImageEncoders().FirstOrDefault(x => x.FormatID == image.RawFormat.Guid)?.MimeType; if (mimeType is null) { mimeType = "image/png"; } - var bytes = ImageToBytes(_image.RawFormat); + var bytes = ImageToBytes(image.RawFormat, options.ScaleFactor); var base64 = Convert.ToBase64String(bytes); return $"data:{mimeType};base64,{base64}"; } + /// + /// Outputs a JPEG for the default scale factor + /// public byte[] ToJPEG(int quality) { - return ImageToBytes(ImageFormat.Jpeg, 1.0d, quality); + return ImageToBytes(ImageFormat.Jpeg, 1.0f, quality); } + /// + /// Outputs a PNG for the specified scale factor + /// public byte[] ToPNG(ToPNGOptions options) { return ImageToBytes(ImageFormat.Png, options.ScaleFactor); } - - private byte[] ImageToBytes(ImageFormat imageFormat, double scaleFactor = 1.0d, int quality = 100) + + private byte[] ImageToBytes(ImageFormat imageFormat = null, float scaleFactor = 1.0f, int quality = 100) { - using (var ms = new MemoryStream()) + using var ms = new MemoryStream(); + + if (_images.ContainsKey(scaleFactor)) { - Image img = _image; + var image = _images[scaleFactor]; + var encoderCodecInfo = GetEncoder(imageFormat ?? image.RawFormat); + var encoder = Encoder.Quality; - if (Math.Abs(scaleFactor - 1.0d) > 0.0) + var encoderParameters = new EncoderParameters(1) { - img = Resize(_image.Width, _image.Height, scaleFactor); - } - - ImageCodecInfo encoderCodecInfo = GetEncoder(imageFormat); - Encoder encoder = Encoder.Quality; - - EncoderParameters encoderParameters = new EncoderParameters(1) - { - Param = new [] + Param = new[] { new EncoderParameter(encoder, quality) - } + } }; - img.Save(ms, encoderCodecInfo, encoderParameters); - + image.Save(ms, encoderCodecInfo, encoderParameters); + return ms.ToArray(); } + + return null; } - private Image Resize(int? width, int? height, double scaleFactor = 1.0d) + private Image Resize(int? width, int? height, float scaleFactor = 1.0f) { - using (var g = Graphics.FromImage(_image)) + if (!_images.ContainsKey(scaleFactor) || (width is null && height is null)) + { + return null; + } + + var image = _images[scaleFactor]; + using (var g = Graphics.FromImage(image)) { g.CompositingQuality = CompositingQuality.HighQuality; - var bmp = new Bitmap((int)Math.Round(width ?? _image.Width * scaleFactor), (int)Math.Round(height ?? _image.Height * scaleFactor)); + var aspect = GetAspectRatio(scaleFactor); + + width ??= Convert.ToInt32(image.Width * aspect); + height ??= Convert.ToInt32(image.Height * aspect); + + width = Convert.ToInt32(width * scaleFactor); + height = Convert.ToInt32(height * scaleFactor); + + var bmp = new Bitmap(width.Value, height.Value); g.DrawImage(bmp, - new System.Drawing.Rectangle(0, 0, _image.Width, _image.Height), + new System.Drawing.Rectangle(0, 0, image.Width, image.Height), new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel); @@ -229,15 +379,40 @@ namespace ElectronNET.API.Entities } } - private Image BytesToImage(byte[] bytes, ImageFormat imageFormat) + private Image Crop(int? x, int? y, int? width, int? height, float scaleFactor = 1.0f) { - var ms = new MemoryStream(bytes); - return Image.FromStream(ms); + if (!_images.ContainsKey(scaleFactor)) + { + return null; + } + + var image = _images[scaleFactor]; + using (var g = Graphics.FromImage(image)) + { + g.CompositingQuality = CompositingQuality.HighQuality; + + x ??= 0; + y ??= 0; + + x = Convert.ToInt32(x * scaleFactor); + y = Convert.ToInt32(y * scaleFactor); + + width ??= image.Width; + height ??= image.Height; + + width = Convert.ToInt32(width * scaleFactor); + height = Convert.ToInt32(height * scaleFactor); + + var bmp = new Bitmap(width.Value, height.Value); + g.DrawImage(bmp, new System.Drawing.Rectangle(0, 0, image.Width, image.Height), new System.Drawing.Rectangle(x.Value, y.Value, width.Value, height.Value), GraphicsUnit.Pixel); + + return bmp; + } } private ImageCodecInfo GetEncoder(ImageFormat format) { - ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders(); + var codecs = ImageCodecInfo.GetImageDecoders(); foreach (ImageCodecInfo codec in codecs) { if (codec.FormatID == format.Guid) @@ -248,9 +423,32 @@ namespace ElectronNET.API.Entities return null; } - internal byte[] GetBytes() + internal Dictionary GetAllScaledImages() { - return ImageToBytes(_image.RawFormat); + var dict = new Dictionary(); + try + { + foreach (var (scale, image) in _images) + { + dict.Add(scale, Convert.ToBase64String(ImageToBytes(null, scale))); + } + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + + return dict; + } + + internal Image GetScale(float scaleFactor) + { + if (_images.ContainsKey(scaleFactor)) + { + return _images[scaleFactor]; + } + + return null; } } } diff --git a/ElectronNET.API/Entities/NativeImageJsonConverter.cs b/ElectronNET.API/Entities/NativeImageJsonConverter.cs new file mode 100644 index 0000000..a82c38e --- /dev/null +++ b/ElectronNET.API/Entities/NativeImageJsonConverter.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using Newtonsoft.Json; + +namespace ElectronNET.API.Entities +{ + internal class NativeImageJsonConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + if (value is NativeImage nativeImage) + { + var scaledImages = nativeImage.GetAllScaledImages(); + serializer.Serialize(writer, scaledImages); + } + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + var dict = serializer.Deserialize>(reader); + var newDictionary = new Dictionary(); + foreach (var item in dict) + { + var bytes = Convert.FromBase64String(item.Value); + newDictionary.Add(item.Key, Image.FromStream(new MemoryStream(bytes))); + } + return new NativeImage(newDictionary); + } + + public override bool CanConvert(Type objectType) => objectType == typeof(NativeImage); + } +} diff --git a/ElectronNET.API/Entities/ToBitmapOptions.cs b/ElectronNET.API/Entities/ToBitmapOptions.cs index e2ba845..4be12b3 100644 --- a/ElectronNET.API/Entities/ToBitmapOptions.cs +++ b/ElectronNET.API/Entities/ToBitmapOptions.cs @@ -6,6 +6,6 @@ namespace ElectronNET.API.Entities { public class ToBitmapOptions { - public double ScaleFactor { get; set; } = 1.0d; + public float ScaleFactor { get; set; } = 1.0f; } } diff --git a/ElectronNET.API/Entities/ToDataUrlOptions.cs b/ElectronNET.API/Entities/ToDataUrlOptions.cs index 09c2b79..bb597fe 100644 --- a/ElectronNET.API/Entities/ToDataUrlOptions.cs +++ b/ElectronNET.API/Entities/ToDataUrlOptions.cs @@ -6,6 +6,6 @@ namespace ElectronNET.API.Entities { public class ToDataUrlOptions { - public double ScaleFactor { get; set; } = 1.0d; + public float ScaleFactor { get; set; } = 1.0f; } } diff --git a/ElectronNET.API/Entities/ToPNGOptions.cs b/ElectronNET.API/Entities/ToPNGOptions.cs index 580d4d5..40b02b9 100644 --- a/ElectronNET.API/Entities/ToPNGOptions.cs +++ b/ElectronNET.API/Entities/ToPNGOptions.cs @@ -6,6 +6,6 @@ namespace ElectronNET.API.Entities { public class ToPNGOptions { - public double ScaleFactor { get; set; } = 1.0d; + public float ScaleFactor { get; set; } = 1.0f; } } diff --git a/ElectronNET.Host/api/clipboard.js b/ElectronNET.Host/api/clipboard.js index 1775188..f32c6c7 100644 --- a/ElectronNET.Host/api/clipboard.js +++ b/ElectronNET.Host/api/clipboard.js @@ -50,11 +50,18 @@ module.exports = (socket) => { }); socket.on('clipboard-readImage', (type) => { const image = electron_1.clipboard.readImage(type); - electronSocket.emit('clipboard-readImage-Completed', image.getNativeHandle().buffer); + electronSocket.emit('clipboard-readImage-Completed', { 1: image.toPNG().toString('base64') }); }); socket.on('clipboard-writeImage', (data, type) => { - const buff = Buffer.from(JSON.parse(data), 'base64'); - const ni = electron_1.nativeImage.createFromBuffer(buff); + var data = JSON.parse(data); + const ni = electron_1.nativeImage.createEmpty(); + for (var i in data) { + var scaleFactor = i; + var bytes = data[i]; + var buff = Buffer.from(bytes, 'base64'); + ni.addRepresentation({ scaleFactor: scaleFactor, buffer: buff }); + } + electron_1.clipboard.writeImage(ni, type); }); }; diff --git a/ElectronNET.Host/api/clipboard.ts b/ElectronNET.Host/api/clipboard.ts index 0f73416..0cbca39 100644 --- a/ElectronNET.Host/api/clipboard.ts +++ b/ElectronNET.Host/api/clipboard.ts @@ -63,13 +63,19 @@ export = (socket: SocketIO.Socket) => { socket.on('clipboard-readImage', (type) => { var image = clipboard.readImage(type); - var b64 = image.getNativeHandle().buffer.toString('base64'); - electronSocket.emit('clipboard-readImage-Completed', b64); + electronSocket.emit('clipboard-readImage-Completed', { 1: image.toPNG().toString('base64') }); }); socket.on('clipboard-writeImage', (data, type) => { - var buff = Buffer.from(JSON.parse(data), 'base64'); - const ni = nativeImage.createFromBuffer(buff); + var data = JSON.parse(data); + const ni = nativeImage.createEmpty(); + for (var i in data) { + var scaleFactor = i; + var bytes = data[i]; + var buff = Buffer.from(bytes, 'base64'); + ni.addRepresentation({ scaleFactor: +scaleFactor, buffer: buff }); + } + clipboard.writeImage(ni, type); }); }; diff --git a/ElectronNET.WebApp/Controllers/ClipboardController.cs b/ElectronNET.WebApp/Controllers/ClipboardController.cs index 631de9f..a290236 100644 --- a/ElectronNET.WebApp/Controllers/ClipboardController.cs +++ b/ElectronNET.WebApp/Controllers/ClipboardController.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Mvc; using ElectronNET.API; using System.Linq; using ElectronNET.API.Entities; +using Newtonsoft.Json; namespace ElectronNET.WebApp.Controllers { @@ -33,6 +34,13 @@ namespace ElectronNET.WebApp.Controllers var nativeImage = NativeImage.CreateFromDataURL(test.ToString()); Electron.Clipboard.WriteImage(nativeImage); }); + + Electron.IpcMain.On("paste-image-to", async test => + { + var nativeImage = await Electron.Clipboard.ReadImageAsync(); + var mainWindow = Electron.WindowManager.BrowserWindows.First(); + Electron.IpcMain.Send(mainWindow, "paste-image-from", JsonConvert.SerializeObject(nativeImage)); + }); } return View(); diff --git a/ElectronNET.WebApp/Views/Clipboard/Index.cshtml b/ElectronNET.WebApp/Views/Clipboard/Index.cshtml index 94e274a..9926476 100644 --- a/ElectronNET.WebApp/Views/Clipboard/Index.cshtml +++ b/ElectronNET.WebApp/Views/Clipboard/Index.cshtml @@ -101,7 +101,6 @@ pasteBtn.addEventListener('click', () => {
-

In this example we copy an image to the Clipboard. After clicking 'Copy' use the text area to paste (CMD + V or CTRL + V) the image from the clipboard.

Main Process (C#)
@@ -129,9 +128,45 @@ copyBtn.addEventListener('click', () => { +
+
+ +
+
+ + +
+

In this example we paste an image from the Clipboard. After clicking 'Paste', if your clipboard contained an image, the image will show up next to the paste button.

+
Main Process (C#)
+
Electron.IpcMain.On("paste-image-to", async test =>
+{
+    var nativeImage = await Electron.Clipboard.ReadImageAsync();
+    var mainWindow = Electron.WindowManager.BrowserWindows.First();
+    Electron.IpcMain.Send(mainWindow, "paste-image-from", JsonConvert.SerializeObject(nativeImage));
+});
+
+

ProTip

+ Electron.js Support in Electron.NET. +

The clipboard module is built into Electron.js (therefore you can use this in the renderer processes).

+
const { nativeImage, clipboard } = require('electron');
+
+const pasteBtn = document.getElementById('paste-to-image');
+
+copyBtn.addEventListener('click', () => {
+    const image = clipboard.readImage();
+    document.getElementById('image-holder').src = image.toDataURL();
+})
+
+
+
+
+