Dashboard/Quik.Media.Stb/QImageStbi.cs

93 lines
2.8 KiB
C#

using System;
using System.IO;
using System.Runtime.InteropServices;
using Quik.Media;
using Quik.Media.Color;
using Quik.Stb;
namespace Quik.Media.Stb
{
public unsafe class QImageStbi : QImage
{
private readonly StbImage image;
private ImageBuffer buffer;
public override int Width => image.Width;
public override int Height => image.Height;
public override int Depth => 1;
public override QImageFormat InternalFormat => Stb2QImageFormat(image.Format);
public QImageStbi(Stream source)
{
// According to the stbi documentation, only a specific type of PNG
// files are premultiplied out of the box (iPhone PNG). Take the
// precision loss L and move on.
StbImage.FlipVerticallyOnLoad = true;
StbImage.UnpremultiplyOnLoad = true;
image = StbImage.Load(source);
}
public static QImageFormat Stb2QImageFormat(StbiImageFormat src)
{
switch (src)
{
case StbiImageFormat.Grey: return QImageFormat.RedU8;
case StbiImageFormat.Rgb: return QImageFormat.RgbU8;
case StbiImageFormat.Rgba: return QImageFormat.RgbaU8;
case StbiImageFormat.GreyAlpha: return QImageFormat.RaU8;
default: return QImageFormat.Undefined;
}
}
public override void LockBits2d(out QImageLock imageLock, QImageLockOptions options)
{
if (options.MipLevel > 0) throw new Exception("This image has no mip levels.");
buffer?.Dispose();
buffer = new ImageBuffer(options.Format, Width, Height);
QImageLock dst = buffer.Lock();
byte *srcPtr = (byte*)image.ImagePointer;
QImageLock src = new QImageLock(InternalFormat, Width, Height, 1, (IntPtr)srcPtr);
FormatConvert.Convert(dst, src);
if (options.Premultiply)
{
FormatConvert.Premultiply(dst);
}
imageLock = dst;
}
public override void LockBits3d(out QImageLock imageLock, QImageLockOptions options)
{
LockBits2d(out imageLock, options);
}
public override void LockBits3d(out QImageLock imageLock, QImageLockOptions options, int depth)
{
if (depth != 1) throw new ArgumentOutOfRangeException(nameof(depth));
LockBits2d(out imageLock, options);
}
public override void UnlockBits()
{
buffer.Unlock();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
buffer?.Dispose();
image.Dispose();
}
}
}
}