Skip to content

Commit

Permalink
优化 大幅提高截图复制到剪贴板性能
Browse files Browse the repository at this point in the history
  • Loading branch information
MakesYT committed Feb 12, 2025
1 parent 64645a8 commit 9e6d878
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 25 deletions.
19 changes: 18 additions & 1 deletion Core.Window/ClipboardWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Avalonia.Platform;
using Avalonia.Threading;
using Core.SDKs.Services;
using PluginCore;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
Expand Down Expand Up @@ -224,7 +225,23 @@ public async Task<bool> SetImageAsync(Image image)
thread.Start();
return await tcs.Task;
}

[STAThread]
public async Task<bool> SetImageAsync(ScreenCaptureResult screenCaptureResult)
{
var tcs = new TaskCompletionSource<bool>();
var thread = new Thread(() =>
{
var bitmapSource = BitmapSource.Create(
screenCaptureResult.Info.Width, screenCaptureResult.Info.Height,
96, 96,
PixelFormats.Bgra32, null,
screenCaptureResult.Bytes, (((int)screenCaptureResult.Info.Width * PixelFormat.Rgba8888.BitsPerPixel + 31) & ~31) >> 3);
Clipboard.SetImage(bitmapSource);
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return await tcs.Task;
}
private static T BytesToStructure<T>(byte[] bytes)
{
var size = Marshal.SizeOf(typeof(T));
Expand Down
2 changes: 2 additions & 0 deletions Core/SDKs/Services/IClipboardService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#region

using PluginCore;
using SixLabors.ImageSharp;
using Bitmap = Avalonia.Media.Imaging.Bitmap;

Expand All @@ -16,6 +17,7 @@ public interface IClipboardService
Bitmap? GetImage();
bool SetImage(Bitmap image);
Task<bool> SetImageAsync(Image image);
Task<bool> SetImageAsync(ScreenCaptureResult screenCaptureResult);
}

public enum ClipboardType
Expand Down
57 changes: 33 additions & 24 deletions KitopiaAvalonia/Windows/ScreenCaptureWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -895,6 +895,8 @@ private void FinnishCapture()
else if (dragTransformY > 0)
cropH = (int)selectBoxHeight;
else cropH = (int)selectBoxHeight + (int)dragTransformY;
var x = Math.Max((int)dragTransformX, 0);
var y = Math.Max((int)dragTransformY, 0);
if (selectMode)
{
if (_currentWindowInfo.Hwnd != IntPtr.Zero)
Expand All @@ -907,8 +909,8 @@ private void FinnishCapture()
{
selectModeAction.Invoke(new ScreenCaptureInfo()
{
X = Math.Max((int)dragTransformX, 0),
Y = Math.Max((int)dragTransformY, 0),
X = x,
Y = y,
Width = cropW,
Height = cropH,
ScreenInfo = _screenCaptureInfo.ScreenInfo
Expand All @@ -934,52 +936,59 @@ private void FinnishCapture()
content.Width = bitmap.PixelSize.Width;
content.Height = bitmap.PixelSize.Height;
renderTargetBitmap.Render(content);
var boundsHeight = (int)(bitmap.PixelSize.Width * bitmap.PixelSize.Height * 4);
var ptr = Marshal.AllocHGlobal(boundsHeight);
renderTargetBitmap.CopyPixels(new PixelRect(0, 0, bitmap.PixelSize.Width, bitmap.PixelSize.Height),
var bufferSize = cropW * cropH * 4;
var ptr = Marshal.AllocHGlobal(bufferSize);
renderTargetBitmap.CopyPixels(new PixelRect(x, y, cropW, cropH),
ptr,
boundsHeight,
(((int)bitmap.PixelSize.Width * PixelFormat.Rgba8888.BitsPerPixel + 31) & ~31) >> 3
bufferSize,
(((int)cropW * PixelFormat.Rgba8888.BitsPerPixel + 31) & ~31) >> 3
);
var ys = new byte[boundsHeight];
Marshal.Copy(ptr, ys, 0, boundsHeight);
var ys = new byte[bufferSize];
Marshal.Copy(ptr, ys, 0, bufferSize);
Marshal.FreeHGlobal(ptr);
var image = SixLabors.ImageSharp.Image.LoadPixelData<Bgra32>(ys, bitmap.PixelSize.Width,
bitmap.PixelSize.Height);
//image.SaveAsPng("1.png");
var clone = image.Clone(e => e.Crop(new Rectangle(
Math.Max((int)dragTransformX, 0), Math.Max((int)dragTransformY, 0),
cropW, cropH)));
image.Dispose();
if (selectBytesMode)
{
byte[] d = new byte[cropH*cropW*4];
clone.CopyPixelDataTo(d);
Task.Run(() =>
{
selectBytesModeAction.Invoke(new ScreenCaptureResult()
{
Info = new ScreenCaptureInfo()
{

X = Math.Max((int)dragTransformX, 0),
Y = Math.Max((int)dragTransformY, 0),
X = x,
Y = y,
Width = cropW,
Height = cropH,
ScreenInfo = _screenCaptureInfo.ScreenInfo
},
Bytes = d
Bytes = ys
});
clone.Dispose();
}).ContinueWith((e) =>
{
GC.Collect(2,GCCollectionMode.Optimized);
});

}
else
{

ServiceManager.Services.GetService<IClipboardService>()
.SetImageAsync(clone)
.ContinueWith((e) => clone.Dispose());
.SetImageAsync(new ScreenCaptureResult()
{
Info = new ScreenCaptureInfo()
{

X = x,
Y = y,
Width = cropW,
Height = cropH,
ScreenInfo = _screenCaptureInfo.ScreenInfo
},
Bytes = ys
}).ContinueWith((e) =>
{
GC.Collect(2,GCCollectionMode.Optimized);
});
}
bitmap.Dispose();
renderTargetBitmap.Dispose();
Expand Down

0 comments on commit 9e6d878

Please sign in to comment.