csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
4.4 KiB
144 lines
4.4 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using Avalonia.Media;
|
|
using Avalonia.Platform;
|
|
using Avalonia.Rendering;
|
|
using SkiaSharp;
|
|
|
|
namespace Avalonia.Skia
|
|
{
|
|
class BitmapImpl : IRenderTargetBitmapImpl, IWritableBitmapImpl
|
|
{
|
|
public SKBitmap Bitmap { get; private set; }
|
|
|
|
public BitmapImpl(SKBitmap bm)
|
|
{
|
|
Bitmap = bm;
|
|
PixelHeight = bm.Height;
|
|
PixelWidth = bm.Width;
|
|
}
|
|
|
|
public BitmapImpl(int width, int height, PixelFormat? fmt = null)
|
|
{
|
|
PixelHeight = height;
|
|
PixelWidth = width;
|
|
var colorType = fmt?.ToSkColorType() ?? SKImageInfo.PlatformColorType;
|
|
var runtime = AvaloniaLocator.Current?.GetService<IRuntimePlatform>()?.GetRuntimeInfo();
|
|
if (runtime?.IsDesktop == true && runtime?.OperatingSystem == OperatingSystemType.Linux)
|
|
colorType = SKColorType.Bgra8888;
|
|
Bitmap = new SKBitmap(width, height, colorType, SKAlphaType.Premul);
|
|
|
|
using (var context = new BitmapDrawingContext(Bitmap, null))
|
|
{
|
|
context.Clear(Colors.Transparent);
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Bitmap.Dispose();
|
|
}
|
|
|
|
public void Save(string fileName)
|
|
{
|
|
|
|
#if DESKTOP
|
|
if(Bitmap.ColorType != SKColorType.Bgra8888)
|
|
{
|
|
using (var tmp = new BitmapImpl(Bitmap.Copy(SKColorType.Bgra8888)))
|
|
tmp.Save(fileName);
|
|
return;
|
|
}
|
|
|
|
IntPtr length;
|
|
using (var sdb = new System.Drawing.Bitmap(PixelWidth, PixelHeight, Bitmap.RowBytes,
|
|
|
|
System.Drawing.Imaging.PixelFormat.Format32bppArgb,
|
|
|
|
Bitmap.GetPixels(out length)))
|
|
sdb.Save(fileName);
|
|
#else
|
|
//SkiaSharp doesn't expose image encoders yet
|
|
#endif
|
|
}
|
|
|
|
public int PixelWidth { get; private set; }
|
|
public int PixelHeight { get; private set; }
|
|
|
|
class BitmapDrawingContext : DrawingContextImpl
|
|
{
|
|
private readonly SKSurface _surface;
|
|
|
|
public BitmapDrawingContext(SKBitmap bitmap, IVisualBrushRenderer visualBrushRenderer)
|
|
: this(CreateSurface(bitmap), visualBrushRenderer)
|
|
{
|
|
|
|
}
|
|
|
|
private static SKSurface CreateSurface(SKBitmap bitmap)
|
|
{
|
|
IntPtr length;
|
|
var rv = SKSurface.Create(bitmap.Info, bitmap.GetPixels(out length), bitmap.RowBytes);
|
|
if (rv == null)
|
|
throw new Exception("Unable to create Skia surface");
|
|
return rv;
|
|
}
|
|
|
|
public BitmapDrawingContext(SKSurface surface, IVisualBrushRenderer visualBrushRenderer)
|
|
: base(surface.Canvas, visualBrushRenderer)
|
|
{
|
|
_surface = surface;
|
|
}
|
|
|
|
public override void Dispose()
|
|
{
|
|
base.Dispose();
|
|
_surface.Dispose();
|
|
}
|
|
}
|
|
|
|
public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer)
|
|
{
|
|
return new BitmapDrawingContext(Bitmap, visualBrushRenderer);
|
|
}
|
|
|
|
public void Save(Stream stream)
|
|
{
|
|
IntPtr length;
|
|
using (var image = SKImage.FromPixels(Bitmap.Info, Bitmap.GetPixels(out length), Bitmap.RowBytes))
|
|
using (var data = image.Encode())
|
|
{
|
|
data.SaveTo(stream);
|
|
}
|
|
}
|
|
|
|
class BitmapFramebuffer : ILockedFramebuffer
|
|
{
|
|
private SKBitmap _bmp;
|
|
|
|
public BitmapFramebuffer(SKBitmap bmp)
|
|
{
|
|
_bmp = bmp;
|
|
_bmp.LockPixels();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_bmp.UnlockPixels();
|
|
_bmp = null;
|
|
}
|
|
|
|
public IntPtr Address => _bmp.GetPixels();
|
|
public int Width => _bmp.Width;
|
|
public int Height => _bmp.Height;
|
|
public int RowBytes => _bmp.RowBytes;
|
|
public Size Dpi { get; } = new Size(96, 96);
|
|
public PixelFormat Format => _bmp.ColorType.ToPixelFormat();
|
|
}
|
|
|
|
public ILockedFramebuffer Lock() => new BitmapFramebuffer(Bitmap);
|
|
}
|
|
}
|
|
|