naps2/NAPS2.Lib.WinForms/Scan/Twain/Legacy/DibUtils.cs
2022-09-11 17:48:05 -07:00

83 lines
2.8 KiB
C#

using System.Drawing;
using System.Runtime.InteropServices;
using NAPS2.Images.Gdi;
namespace NAPS2.Scan.Twain.Legacy;
internal class DibUtils
{
[DllImport("gdi32.dll", ExactSpelling = true)]
internal static extern int SetDIBitsToDevice(IntPtr hdc, int xdst, int ydst,
int width, int height, int xsrc, int ysrc, int start, int lines,
IntPtr bitsptr, IntPtr bmiptr, int color);
[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GlobalLock(IntPtr handle);
[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GlobalFree(IntPtr handle);
//THIS METHOD SAVES THE CONTENTS OF THE DIB POINTER INTO A BITMAP OBJECT
public static Bitmap BitmapFromDib(IntPtr pDib, out int bitdepth)
{
IntPtr dibhand = pDib;
IntPtr bmpptr = GlobalLock(dibhand);
IntPtr pixptr = GetPixelInfo(bmpptr);
BitmapInfoHeader binfo = GetDibInfo(bmpptr);
float resx = binfo.biXPelsPerMeter * 0.0254f;
float resy = binfo.biYPelsPerMeter * 0.0254f;
var scannedImage = new Bitmap(binfo.biWidth, binfo.biHeight);
Graphics scannedImageGraphics = Graphics.FromImage(scannedImage);
IntPtr hdc = scannedImageGraphics.GetHdc();
SetDIBitsToDevice(hdc, 0, 0, binfo.biWidth, binfo.biHeight, 0, 0, 0, binfo.biHeight, pixptr, bmpptr, 0);
scannedImageGraphics.ReleaseHdc(hdc);
GlobalFree(dibhand);
scannedImageGraphics.Dispose();
bitdepth = binfo.biBitCount;
scannedImage.SafeSetResolution(resx, resy);
return scannedImage;
}
//THIS METHOD GETS THE POINTER TO THE BITMAP HEADER INFO
private static IntPtr GetPixelInfo(IntPtr bmpPtr)
{
var bmi = (BitmapInfoHeader)Marshal.PtrToStructure(bmpPtr, typeof(BitmapInfoHeader))!;
if (bmi.biSizeImage == 0)
bmi.biSizeImage = (uint)(((((bmi.biWidth * bmi.biBitCount) + 31) & ~31) >> 3) * bmi.biHeight);
var p = (int)bmi.biClrUsed;
if ((p == 0) && (bmi.biBitCount <= 8))
p = 1 << bmi.biBitCount;
p = (p * 4) + (int)bmi.biSize + (int)bmpPtr;
return (IntPtr)p;
}
//THIS METHOD GETS THE POINTER TO THE BITMAP HEADER INFO
private static BitmapInfoHeader GetDibInfo(IntPtr bmpPtr)
{
var bmi = (BitmapInfoHeader)Marshal.PtrToStructure(bmpPtr, typeof(BitmapInfoHeader))!;
return bmi;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct BitmapInfoHeader
{
public uint biSize;
public int biWidth;
public int biHeight;
public ushort biPlanes;
public ushort biBitCount;
public uint biCompression;
public uint biSizeImage;
public int biXPelsPerMeter;
public int biYPelsPerMeter;
public uint biClrUsed;
public uint biClrImportant;
public void Init()
{
biSize = (uint)Marshal.SizeOf(this);
}
}