93 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			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();
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| } |