2023-07-09 16:46:35 +02:00
|
|
|
using System;
|
|
|
|
using System.IO;
|
2024-07-17 22:18:20 +02:00
|
|
|
using Dashboard.Media.Color;
|
2024-06-21 08:52:29 +02:00
|
|
|
using ReFuel.Stb;
|
2023-07-09 16:46:35 +02:00
|
|
|
|
2024-07-17 22:18:20 +02:00
|
|
|
namespace Dashboard.Media.Defaults
|
2023-07-09 16:46:35 +02:00
|
|
|
{
|
2024-07-28 13:19:13 +02:00
|
|
|
public unsafe class ImageStbi : Image
|
2023-07-09 16:46:35 +02:00
|
|
|
{
|
|
|
|
private readonly StbImage image;
|
2023-09-22 18:30:17 +02:00
|
|
|
private QImageBuffer buffer;
|
2024-04-14 21:51:10 +02:00
|
|
|
private bool isSdf = false;
|
2023-07-09 16:46:35 +02:00
|
|
|
|
|
|
|
public override int Width => image.Width;
|
|
|
|
|
|
|
|
public override int Height => image.Height;
|
|
|
|
|
|
|
|
public override int Depth => 1;
|
2024-04-14 21:51:10 +02:00
|
|
|
public override bool IsSdf => isSdf;
|
2024-07-28 13:19:13 +02:00
|
|
|
public override ImageFormat InternalFormat => Stb2QImageFormat(image.Format);
|
2023-07-09 16:46:35 +02:00
|
|
|
|
2024-07-28 13:19:13 +02:00
|
|
|
public ImageStbi(Stream source)
|
2023-07-09 16:46:35 +02:00
|
|
|
{
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
2024-07-28 13:19:13 +02:00
|
|
|
public static ImageFormat Stb2QImageFormat(StbiImageFormat src)
|
2023-07-09 16:46:35 +02:00
|
|
|
{
|
|
|
|
switch (src)
|
|
|
|
{
|
2024-07-28 13:19:13 +02:00
|
|
|
case StbiImageFormat.Grey: return ImageFormat.RedU8;
|
|
|
|
case StbiImageFormat.Rgb: return ImageFormat.RgbU8;
|
|
|
|
case StbiImageFormat.Rgba: return ImageFormat.RgbaU8;
|
|
|
|
case StbiImageFormat.GreyAlpha: return ImageFormat.RaU8;
|
|
|
|
default: return ImageFormat.Undefined;
|
2023-07-09 16:46:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void LockBits2d(out QImageLock imageLock, QImageLockOptions options)
|
|
|
|
{
|
|
|
|
if (options.MipLevel > 0) throw new Exception("This image has no mip levels.");
|
|
|
|
|
|
|
|
buffer?.Dispose();
|
2023-09-22 18:30:17 +02:00
|
|
|
buffer = new QImageBuffer(options.Format, Width, Height);
|
|
|
|
buffer.LockBits2d(out QImageLock dst, QImageLockOptions.Default);
|
2023-07-09 16:46:35 +02:00
|
|
|
|
|
|
|
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()
|
|
|
|
{
|
2023-09-22 18:30:17 +02:00
|
|
|
buffer.UnlockBits();
|
2023-07-09 16:46:35 +02:00
|
|
|
}
|
|
|
|
|
2024-04-14 21:51:10 +02:00
|
|
|
public void SdfHint(bool value = true)
|
|
|
|
{
|
|
|
|
isSdf = value;
|
|
|
|
}
|
|
|
|
|
2023-07-09 16:46:35 +02:00
|
|
|
protected override void Dispose(bool disposing)
|
|
|
|
{
|
|
|
|
base.Dispose(disposing);
|
|
|
|
|
|
|
|
if (disposing)
|
|
|
|
{
|
|
|
|
buffer?.Dispose();
|
|
|
|
image.Dispose();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|