Dashboard/Quik/Media/Color/ImageBuffer.cs

92 lines
3.2 KiB
C#
Raw Normal View History

using System;
using System.Runtime.InteropServices;
2023-09-22 18:30:17 +02:00
namespace Quik.Media
{
2023-09-22 18:30:17 +02:00
public class QImageBuffer : QImage
{
private byte[] buffer;
GCHandle handle;
2023-09-22 18:30:17 +02:00
public override QImageFormat InternalFormat { get; }
public override int Width { get; }
public override int Height { get; }
public override int Depth { get; }
2023-09-22 18:30:17 +02:00
public QImageBuffer(QImageFormat format, int width, int height, int depth = 1)
{
2023-09-22 18:30:17 +02:00
InternalFormat = format;
Width = width;
Height = height;
Depth = depth;
2023-09-22 18:30:17 +02:00
buffer = new byte[width * height * depth * format.BytesPerPixel()];
}
2023-09-22 18:30:17 +02:00
~QImageBuffer()
{
Dispose(false);
}
2023-09-22 18:30:17 +02:00
private QImageLock Lock()
{
handle.Free();
handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0);
2023-09-22 18:30:17 +02:00
return new QImageLock(InternalFormat, Width, Height, Depth, ptr);
}
2023-09-22 18:30:17 +02:00
protected override void Dispose(bool disposing)
{
2023-09-22 18:30:17 +02:00
if (handle.IsAllocated) handle.Free();
buffer = null;
GC.SuppressFinalize(this);
}
2023-09-22 18:30:17 +02:00
public override void LockBits2d(out QImageLock imageLock, QImageLockOptions options)
{
2023-09-22 18:30:17 +02:00
if (options.Format != options.Format) throw new InvalidOperationException("This image type cannot be converted.");
if (Depth > 1) throw new InvalidOperationException("This texture has a depth component.");
2023-09-22 18:30:17 +02:00
UnlockBits();
2023-09-22 18:30:17 +02:00
handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0);
imageLock = new QImageLock(InternalFormat, Width, Height, Depth, ptr);
}
public override void LockBits3d(out QImageLock imageLock, QImageLockOptions options)
{
if (options.Format != options.Format) throw new InvalidOperationException("This image type cannot be converted.");
UnlockBits();
handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0);
imageLock = new QImageLock(InternalFormat, Width, Height, Depth, ptr);
}
public override void LockBits3d(out QImageLock imageLock, QImageLockOptions options, int depth)
{
if (options.Format != options.Format) throw new InvalidOperationException("This image type cannot be converted.");
if (depth < 0 || depth > Depth)
throw new ArgumentOutOfRangeException(nameof(depth), "Depth must be in range.");
UnlockBits();
handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0);
imageLock = new QImageLock(
InternalFormat,
Width,
Height,
1,
ptr + (depth * Width * Height * InternalFormat.BytesPerPixel()));
}
2023-09-22 18:30:17 +02:00
public override void UnlockBits()
{
2023-09-22 18:30:17 +02:00
if (handle.IsAllocated)
handle.Free();
}
}
}