92 lines
3.2 KiB
C#
92 lines
3.2 KiB
C#
using System;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace Quik.Media
|
|
{
|
|
public class QImageBuffer : QImage
|
|
{
|
|
private byte[] buffer;
|
|
GCHandle handle;
|
|
|
|
public override QImageFormat InternalFormat { get; }
|
|
public override int Width { get; }
|
|
public override int Height { get; }
|
|
public override int Depth { get; }
|
|
|
|
public QImageBuffer(QImageFormat format, int width, int height, int depth = 1)
|
|
{
|
|
InternalFormat = format;
|
|
Width = width;
|
|
Height = height;
|
|
Depth = depth;
|
|
|
|
buffer = new byte[width * height * depth * format.BytesPerPixel()];
|
|
}
|
|
~QImageBuffer()
|
|
{
|
|
Dispose(false);
|
|
}
|
|
|
|
private QImageLock Lock()
|
|
{
|
|
handle.Free();
|
|
handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
|
|
IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0);
|
|
return new QImageLock(InternalFormat, Width, Height, Depth, ptr);
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (handle.IsAllocated) handle.Free();
|
|
buffer = null;
|
|
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
public override void LockBits2d(out QImageLock imageLock, QImageLockOptions options)
|
|
{
|
|
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.");
|
|
|
|
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)
|
|
{
|
|
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()));
|
|
}
|
|
|
|
public override void UnlockBits()
|
|
{
|
|
if (handle.IsAllocated)
|
|
handle.Free();
|
|
}
|
|
}
|
|
} |