using System; namespace Quik.Media.Color { public unsafe struct LockIO { public QImageLock Lock { get; } public int Width => Lock.Width; public int Height => Lock.Height; public int Depth => Depth; public QImageFormat Format => Lock.Format; public LockIO(QImageLock imageLock) { if (!imageLock.Format.IsU8()) throw new Exception("Can only read/write U8 format images"); Lock = imageLock; } public QColor this[int index] { get { int chan = Format.Channels(); byte *ptr = (byte*)Lock.ImagePtr + chan * index; switch (Format) { default: case QImageFormat.RedU8: return new QColor(ptr[0], 0, 0, 255); case QImageFormat.AlphaU8: return new QColor(0, 0, 0, ptr[0]); case QImageFormat.RaU8: return new QColor(ptr[0], 0, 0, ptr[1]); case QImageFormat.RgbU8: return new QColor(ptr[0], ptr[1], ptr[2], 255); case QImageFormat.RgbaU8: return new QColor(ptr[0], ptr[1], ptr[2], ptr[3]); } } set { int chan = Format.Channels(); byte *ptr = (byte*)Lock.ImagePtr + chan * index; switch (Format) { default: case QImageFormat.RedU8: ptr[0] = value.R; break; case QImageFormat.AlphaU8: ptr[0] = value.A; break; case QImageFormat.RaU8: ptr[0] = value.R; ptr[1] = value.A; break; case QImageFormat.RgbU8: ptr[0] = value.R; ptr[1] = value.G; ptr[2] = value.B; break; case QImageFormat.RgbaU8: ptr[0] = value.R; ptr[1] = value.G; ptr[2] = value.B; ptr[3] = value.A; break; } } } public QColor this[int x, int y, int z = 0] { get => this[x + y * Width + z * Width * Height]; set => this[x + y * Width + z * Width * Height] = value; } } public unsafe struct LockIOF { public QImageLock Lock { get; } public int Width => Lock.Width; public int Height => Lock.Height; public int Depth => Depth; public QImageFormat Format => Lock.Format; public LockIOF(QImageLock imageLock) { if (!imageLock.Format.IsFloat()) throw new Exception("Can only read/write U8 format images"); Lock = imageLock; } public QColorF this[int index] { get { int chan = Format.Channels(); float *ptr = (float*)Lock.ImagePtr + chan * index; switch (Format) { default: case QImageFormat.RedU8: return new QColorF(ptr[0], 0, 0, 255); case QImageFormat.AlphaU8: return new QColorF(0, 0, 0, ptr[0]); case QImageFormat.RaU8: return new QColorF(ptr[0], 0, 0, ptr[1]); case QImageFormat.RgbU8: return new QColorF(ptr[0], ptr[1], ptr[2], 255); case QImageFormat.RgbaU8: return new QColorF(ptr[0], ptr[1], ptr[2], ptr[3]); } } set { int chan = Format.Channels(); float *ptr = (float*)Lock.ImagePtr + chan * index; switch (Format) { default: case QImageFormat.RedU8: ptr[0] = value.R; break; case QImageFormat.AlphaU8: ptr[0] = value.A; break; case QImageFormat.RaU8: ptr[0] = value.R; ptr[1] = value.A; break; case QImageFormat.RgbU8: ptr[0] = value.R; ptr[1] = value.G; ptr[2] = value.B; break; case QImageFormat.RgbaU8: ptr[0] = value.R; ptr[1] = value.G; ptr[2] = value.B; ptr[3] = value.A; break; } } } public QColorF this[int x, int y, int z = 0] { get => this[x + y * Width + z * Width * Height]; set => this[x + y * Width + z * Width * Height] = value; } } }