.+)");
+ var actualData = parsedDataUrl.Groups["data"].Value;
+ var type = parsedDataUrl.Groups["type"].Value;
+ var binData = Convert.FromBase64String(actualData);
- // public void AddRepresentation(AddRepresentationOptions options)
- // {
- // throw new NotImplementedException();
- // }
+ 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
+ };
- // public NativeImage Crop(Rectangle rect)
- // {
- // throw new NotImplementedException();
- // }
+ return new NativeImage(binData, imageFormat);
+ }
- // public int GetAspectRatio()
- // {
- // throw new NotImplementedException();
- // }
+ public static NativeImage CreateFromPath(string path)
+ {
+ return new NativeImage(path);
+ }
- // public byte[] GetBitmap()
- // {
- // throw new NotImplementedException();
- // }
+ public NativeImage()
+ {
+ }
- // public byte[] GetBitmap(BitmapOptions options)
- // {
- // throw new NotImplementedException();
- // }
+ public NativeImage(Bitmap bitmap)
+ {
+ _image = bitmap;
+ }
+ public NativeImage(string path)
+ {
+ _image = Image.FromFile(path);
+ }
- // public byte[] GetNativeHandle()
- // {
- // throw new NotImplementedException();
- // }
- // public Size GetSize()
- // {
- // throw new NotImplementedException();
- // }
+ public NativeImage(byte[] buffer)
+ {
+ var ms = new MemoryStream(buffer);
+ _image = Image.FromStream(ms);
+ }
- // public bool IsEmpty()
- // {
- // throw new NotImplementedException();
- // }
+ public NativeImage(byte[] buffer, ImageFormat imageFormat)
+ {
+ _image = BytesToImage(buffer, imageFormat);
+ }
- // public bool IsTemplateImage()
- // {
- // throw new NotImplementedException();
- // }
+ public Image GetBitmap()
+ {
+ return _image;
+ }
- // public NativeImage Resize(ResizeOptions options)
- // {
- // throw new NotImplementedException();
- // }
+ public NativeImage Crop(Rectangle rect)
+ {
+ using (var g = Graphics.FromImage(_image))
+ {
+ 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);
- // public void SetTemplateImage(bool option)
- // {
- // throw new NotImplementedException();
- // }
+ return new NativeImage(bmp);
+ }
+ }
+ public void AddRepresentation(AddRepresentationOptions options)
+ {
+ if (options.Buffer.Length > 0)
+ {
+ _image = CreateFromBuffer(options.Buffer).GetBitmap();
+ }
+ else if (!string.IsNullOrEmpty(options.DataUrl))
+ {
+ _image = CreateFromDataURL(options.DataUrl).GetBitmap();
+ }
+ }
- // public byte[] ToBitmap(ToBitmapOptions options)
- // {
- // throw new NotImplementedException();
- // }
+ public double GetAspectRatio => _image.Width / _image.Height;
- // public string ToDataURL(ToDataURLOptions options)
- // {
- // throw new NotImplementedException();
- // }
- // public byte[] ToJPEG(int quality)
- // {
- // throw new NotImplementedException();
- // }
+ public byte[] GetBitmap(BitmapOptions options)
+ {
+ return ImageToBytes(_image.RawFormat);
+ }
- // public byte[] ToPNG(ToPNGOptions options)
- // {
- // throw new NotImplementedException();
- // }
+ public byte[] GetNativeHandle()
+ {
+ return ImageToBytes(_image.RawFormat);
+ }
+
+ public Size GetSize()
+ {
+ return new Size
+ {
+ Width = _image.Width,
+ Height = _image.Height
+ };
+ }
+
+ public bool IsEmpty()
+ {
+ return _image == null;
+ }
+
+ ///
+ /// Deprecated. Whether the image is a template image.
+ ///
+ ///
+ public bool IsTemplateImage => _isTemplateImage;
+
+ ///
+ /// Deprecated. Marks the image as a template image.
+ ///
+ public void SetTemplateImage(bool option)
+ {
+ _isTemplateImage = option;
+ }
+
+
+ public NativeImage Resize(ResizeOptions options)
+ {
+ return new NativeImage((Bitmap)Resize(options.Width, options.Height));
+ }
+
+ public byte[] ToBitmap(ToBitmapOptions options)
+ {
+ return ImageToBytes(_image.RawFormat);
+ }
+
+ public string ToDataURL(ToDataUrlOptions options)
+ {
+ 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 base64 = Convert.ToBase64String(bytes);
+
+ return $"data:{mimeType};base64,{base64}";
+ }
+
+ public byte[] ToJPEG(int quality)
+ {
+ return ImageToBytes(ImageFormat.Jpeg, 1.0d, quality);
+ }
+
+ public byte[] ToPNG(ToPNGOptions options)
+ {
+ return ImageToBytes(ImageFormat.Png, options.ScaleFactor);
+ }
+
+ private byte[] ImageToBytes(ImageFormat imageFormat, double scaleFactor = 1.0d, int quality = 100)
+ {
+ using (var ms = new MemoryStream())
+ {
+ Image img = _image;
+
+ if (Math.Abs(scaleFactor - 1.0d) > 0.0)
+ {
+ img = Resize(_image.Width, _image.Height, scaleFactor);
+ }
+
+ ImageCodecInfo encoderCodecInfo = GetEncoder(imageFormat);
+ Encoder encoder = Encoder.Quality;
+
+ EncoderParameters encoderParameters = new EncoderParameters(1)
+ {
+ Param = new []
+ {
+ new EncoderParameter(encoder, quality)
+ }
+ };
+
+ img.Save(ms, encoderCodecInfo, encoderParameters);
+
+ return ms.ToArray();
+ }
+ }
+
+ private Image Resize(int? width, int? height, double scaleFactor = 1.0d)
+ {
+ 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));
+ g.DrawImage(bmp,
+ new System.Drawing.Rectangle(0, 0, _image.Width, _image.Height),
+ new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height),
+ GraphicsUnit.Pixel);
+
+ return bmp;
+ }
+ }
+
+ private Image BytesToImage(byte[] bytes, ImageFormat imageFormat)
+ {
+ var ms = new MemoryStream(bytes);
+ return Image.FromStream(ms);
+ }
+
+ private ImageCodecInfo GetEncoder(ImageFormat format)
+ {
+ ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
+ foreach (ImageCodecInfo codec in codecs)
+ {
+ if (codec.FormatID == format.Guid)
+ {
+ return codec;
+ }
+ }
+ return null;
+ }
+
+ internal byte[] GetBytes()
+ {
+ return ImageToBytes(_image.RawFormat);
+ }
}
}
diff --git a/ElectronNET.API/Entities/ResizeOptions.cs b/ElectronNET.API/Entities/ResizeOptions.cs
new file mode 100644
index 0000000..1cc376f
--- /dev/null
+++ b/ElectronNET.API/Entities/ResizeOptions.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ElectronNET.API.Entities
+{
+ public class ResizeOptions
+ {
+ public int? Width { get; set; }
+ public int? Height { get; set; }
+
+ ///
+ /// good, better, or best. Default is "best";
+ ///
+ public string Quality { get; set; } = "best";
+ }
+}
diff --git a/ElectronNET.API/Entities/ToBitmapOptions.cs b/ElectronNET.API/Entities/ToBitmapOptions.cs
new file mode 100644
index 0000000..e2ba845
--- /dev/null
+++ b/ElectronNET.API/Entities/ToBitmapOptions.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ElectronNET.API.Entities
+{
+ public class ToBitmapOptions
+ {
+ public double ScaleFactor { get; set; } = 1.0d;
+ }
+}
diff --git a/ElectronNET.API/Entities/ToDataUrlOptions.cs b/ElectronNET.API/Entities/ToDataUrlOptions.cs
new file mode 100644
index 0000000..09c2b79
--- /dev/null
+++ b/ElectronNET.API/Entities/ToDataUrlOptions.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ElectronNET.API.Entities
+{
+ public class ToDataUrlOptions
+ {
+ public double ScaleFactor { get; set; } = 1.0d;
+ }
+}
diff --git a/ElectronNET.API/Entities/ToPNGOptions.cs b/ElectronNET.API/Entities/ToPNGOptions.cs
new file mode 100644
index 0000000..580d4d5
--- /dev/null
+++ b/ElectronNET.API/Entities/ToPNGOptions.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ElectronNET.API.Entities
+{
+ public class ToPNGOptions
+ {
+ public double ScaleFactor { get; set; } = 1.0d;
+ }
+}
diff --git a/ElectronNET.Host/api/clipboard.js b/ElectronNET.Host/api/clipboard.js
index 610e072..1775188 100644
--- a/ElectronNET.Host/api/clipboard.js
+++ b/ElectronNET.Host/api/clipboard.js
@@ -48,5 +48,14 @@ module.exports = (socket) => {
socket.on('clipboard-write', (data, type) => {
electron_1.clipboard.write(data, type);
});
+ socket.on('clipboard-readImage', (type) => {
+ const image = electron_1.clipboard.readImage(type);
+ electronSocket.emit('clipboard-readImage-Completed', image.getNativeHandle().buffer);
+ });
+ socket.on('clipboard-writeImage', (data, type) => {
+ const buff = Buffer.from(JSON.parse(data), 'base64');
+ const ni = electron_1.nativeImage.createFromBuffer(buff);
+ electron_1.clipboard.writeImage(ni, type);
+ });
};
//# sourceMappingURL=clipboard.js.map
\ No newline at end of file
diff --git a/ElectronNET.Host/api/clipboard.ts b/ElectronNET.Host/api/clipboard.ts
index f0f92c1..0f73416 100644
--- a/ElectronNET.Host/api/clipboard.ts
+++ b/ElectronNET.Host/api/clipboard.ts
@@ -1,4 +1,4 @@
-import { clipboard } from 'electron';
+import { clipboard, nativeImage } from 'electron';
let electronSocket;
export = (socket: SocketIO.Socket) => {
@@ -60,4 +60,16 @@ export = (socket: SocketIO.Socket) => {
socket.on('clipboard-write', (data, type) => {
clipboard.write(data, type);
});
+
+ socket.on('clipboard-readImage', (type) => {
+ var image = clipboard.readImage(type);
+ var b64 = image.getNativeHandle().buffer.toString('base64');
+ electronSocket.emit('clipboard-readImage-Completed', b64);
+ });
+
+ socket.on('clipboard-writeImage', (data, type) => {
+ var buff = Buffer.from(JSON.parse(data), 'base64');
+ const ni = nativeImage.createFromBuffer(buff);
+ clipboard.writeImage(ni, type);
+ });
};
diff --git a/ElectronNET.WebApp/Controllers/ClipboardController.cs b/ElectronNET.WebApp/Controllers/ClipboardController.cs
index 27f8d9e..631de9f 100644
--- a/ElectronNET.WebApp/Controllers/ClipboardController.cs
+++ b/ElectronNET.WebApp/Controllers/ClipboardController.cs
@@ -1,6 +1,10 @@
-using Microsoft.AspNetCore.Mvc;
+using System;
+using System.Drawing;
+using System.IO;
+using Microsoft.AspNetCore.Mvc;
using ElectronNET.API;
using System.Linq;
+using ElectronNET.API.Entities;
namespace ElectronNET.WebApp.Controllers
{
@@ -23,6 +27,12 @@ namespace ElectronNET.WebApp.Controllers
var mainWindow = Electron.WindowManager.BrowserWindows.First();
Electron.IpcMain.Send(mainWindow, "paste-from", pasteText);
});
+
+ Electron.IpcMain.On("copy-image-to", (test) =>
+ {
+ var nativeImage = NativeImage.CreateFromDataURL(test.ToString());
+ Electron.Clipboard.WriteImage(nativeImage);
+ });
}
return View();
diff --git a/ElectronNET.WebApp/Controllers/MenusController.cs b/ElectronNET.WebApp/Controllers/MenusController.cs
index 4e9d8ec..6a17255 100644
--- a/ElectronNET.WebApp/Controllers/MenusController.cs
+++ b/ElectronNET.WebApp/Controllers/MenusController.cs
@@ -112,13 +112,13 @@ namespace ElectronNET.WebApp.Controllers
new MenuItem { Label = "Electron.NET", Type = MenuType.checkbox, Checked = true }
};
- var mainWindow = Electron.WindowManager.BrowserWindows.First();
+ /*var mainWindow = Electron.WindowManager.BrowserWindows.First();
Electron.Menu.SetContextMenu(mainWindow, menu);
Electron.IpcMain.On("show-context-menu", (args) =>
{
Electron.Menu.ContextMenuPopup(mainWindow);
- });
+ });*/
}
}
}
\ No newline at end of file
diff --git a/ElectronNET.WebApp/Views/Clipboard/Index.cshtml b/ElectronNET.WebApp/Views/Clipboard/Index.cshtml
index 77e3098..94e274a 100644
--- a/ElectronNET.WebApp/Views/Clipboard/Index.cshtml
+++ b/ElectronNET.WebApp/Views/Clipboard/Index.cshtml
@@ -8,7 +8,7 @@
The Electron.Clipboard provides methods to perform copy and paste operations.
This module also has methods for copying text as markup (HTML) to the clipboard.
-
+
You find the sample source code in Controllers\ClipboardController.cs.
@@ -90,24 +90,153 @@ pasteBtn.addEventListener('click', () => {
-
diff --git a/ElectronNET.WebApp/wwwroot/assets/css/demo.css b/ElectronNET.WebApp/wwwroot/assets/css/demo.css
index 96afc4b..4ffa4a1 100644
--- a/ElectronNET.WebApp/wwwroot/assets/css/demo.css
+++ b/ElectronNET.WebApp/wwwroot/assets/css/demo.css
@@ -203,3 +203,7 @@
font-weight: 600;
}
+/* Clipboard paste image ------------------ */
+.demo-image-box {
+ padding-left: 15px;
+}
\ No newline at end of file