mirror of
https://github.com/soukoku/ntwain.git
synced 2025-04-05 20:59:23 +08:00
Update image parse code.
This commit is contained in:
parent
eef0b9db92
commit
9ba2b0d0e0
@ -88,9 +88,6 @@
|
|||||||
<Compile Include="..\NTwain\IDataSource.cs">
|
<Compile Include="..\NTwain\IDataSource.cs">
|
||||||
<Link>IDataSource.cs</Link>
|
<Link>IDataSource.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\NTwain\ImageTools.cs">
|
|
||||||
<Link>ImageTools.cs</Link>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\NTwain\IMemoryManager.cs">
|
<Compile Include="..\NTwain\IMemoryManager.cs">
|
||||||
<Link>IMemoryManager.cs</Link>
|
<Link>IMemoryManager.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
@ -100,6 +97,9 @@
|
|||||||
<Compile Include="..\NTwain\Internals\ICommittable.cs">
|
<Compile Include="..\NTwain\Internals\ICommittable.cs">
|
||||||
<Link>Internals\ICommittable.cs</Link>
|
<Link>Internals\ICommittable.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\NTwain\Internals\ImageTools.cs">
|
||||||
|
<Link>Internals\ImageTools.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\NTwain\Internals\InternalMessageLoopHook.cs">
|
<Compile Include="..\NTwain\Internals\InternalMessageLoopHook.cs">
|
||||||
<Link>Internals\InternalMessageLoopHook.cs</Link>
|
<Link>Internals\InternalMessageLoopHook.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
@ -331,6 +331,9 @@
|
|||||||
<Compile Include="..\NTwain\TwainStateException.cs">
|
<Compile Include="..\NTwain\TwainStateException.cs">
|
||||||
<Link>TwainStateException.cs</Link>
|
<Link>TwainStateException.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\NTwain\WpfImageTools.cs">
|
||||||
|
<Link>WpfImageTools.cs</Link>
|
||||||
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="..\NTwain\Properties\Resources.resx">
|
<EmbeddedResource Include="..\NTwain\Properties\Resources.resx">
|
||||||
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Security.Permissions;
|
using System.Security.Permissions;
|
||||||
@ -140,26 +141,28 @@ namespace NTwain
|
|||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the bitmap from the <see cref="NativeData"/> if it's an image.
|
/// Gets the image stream from the <see cref="NativeData"/> if it's an image.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Image GetNativeImage()
|
public Stream GetNativeImageStream()
|
||||||
{
|
{
|
||||||
Image image = null;
|
Stream retVal = null;
|
||||||
|
|
||||||
if (NativeData != IntPtr.Zero)
|
if (NativeData != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
if (ImageTools.IsDib(NativeData))
|
if (ImageTools.IsDib(NativeData))
|
||||||
{
|
{
|
||||||
image = ImageTools.ReadBitmapImage(NativeData);
|
retVal = ImageTools.GetBitmapStream(NativeData);
|
||||||
}
|
}
|
||||||
else if (ImageTools.IsTiff(NativeData))
|
else if (ImageTools.IsTiff(NativeData))
|
||||||
{
|
{
|
||||||
image = ImageTools.ReadTiffImage(NativeData);
|
retVal = ImageTools.GetTiffStream(NativeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return image;
|
return retVal; ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,154 +0,0 @@
|
|||||||
using Microsoft.Win32.SafeHandles;
|
|
||||||
using NTwain.Interop;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Drawing.Imaging;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Security;
|
|
||||||
using System.Text;
|
|
||||||
using System.Windows.Media.Imaging;
|
|
||||||
|
|
||||||
namespace NTwain
|
|
||||||
{
|
|
||||||
public static class ImageTools
|
|
||||||
{
|
|
||||||
internal static bool IsDib(IntPtr data)
|
|
||||||
{
|
|
||||||
// a quick check not guaranteed correct,
|
|
||||||
// compare first 2 bytes to size of struct (which is also the first field)
|
|
||||||
var test = Marshal.ReadInt16(data);
|
|
||||||
// should be 40
|
|
||||||
return test == BITMAPINFOHEADER.GetByteSize();
|
|
||||||
}
|
|
||||||
internal static bool IsTiff(IntPtr data)
|
|
||||||
{
|
|
||||||
var test = Marshal.ReadInt16(data);
|
|
||||||
// should be II
|
|
||||||
return test == 0x4949;
|
|
||||||
}
|
|
||||||
internal static Bitmap ReadBitmapImage(IntPtr data)
|
|
||||||
{
|
|
||||||
Bitmap finalImg = null;
|
|
||||||
Bitmap tempImg = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var header = (BITMAPINFOHEADER)Marshal.PtrToStructure(data, typeof(BITMAPINFOHEADER));
|
|
||||||
|
|
||||||
if (header.Validate())
|
|
||||||
{
|
|
||||||
PixelFormat format = header.GetDrawingPixelFormat();
|
|
||||||
tempImg = new Bitmap(header.biWidth, Math.Abs(header.biHeight), header.GetStride(), format, header.GetScan0(data));
|
|
||||||
ColorPalette pal = header.GetDrawingPalette(data);
|
|
||||||
if (pal != null)
|
|
||||||
{
|
|
||||||
tempImg.Palette = pal;
|
|
||||||
}
|
|
||||||
float xdpi = header.GetXDpi();
|
|
||||||
float ydpi = header.GetYDpi();
|
|
||||||
if (xdpi != 0 && ydpi == 0)
|
|
||||||
{
|
|
||||||
ydpi = xdpi;
|
|
||||||
}
|
|
||||||
else if (ydpi != 0 && xdpi == 0)
|
|
||||||
{
|
|
||||||
xdpi = ydpi;
|
|
||||||
}
|
|
||||||
if (xdpi != 0)
|
|
||||||
{
|
|
||||||
tempImg.SetResolution(xdpi, ydpi);
|
|
||||||
}
|
|
||||||
if (header.IsBottomUpImage)
|
|
||||||
{
|
|
||||||
tempImg.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
|
||||||
}
|
|
||||||
finalImg = tempImg;
|
|
||||||
tempImg = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (tempImg != null)
|
|
||||||
{
|
|
||||||
tempImg.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return finalImg;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static Image ReadTiffImage(IntPtr data)
|
|
||||||
{
|
|
||||||
// this is modified from twain cs sample
|
|
||||||
// http://sourceforge.net/projects/twainforcsharp/?source=typ_redirect
|
|
||||||
|
|
||||||
|
|
||||||
// Find the size of the image so we can turn it into a memory stream...
|
|
||||||
var headerSize = Marshal.SizeOf(typeof(TIFFHEADER));
|
|
||||||
var tagSize = Marshal.SizeOf(typeof(TIFFTAG));
|
|
||||||
var tiffSize = 0;
|
|
||||||
var tagPtr = data.ToInt64() + headerSize;
|
|
||||||
for (int i = 0; i < 999; i++)
|
|
||||||
{
|
|
||||||
tagPtr += (tagSize * i);
|
|
||||||
var tag = (TIFFTAG)Marshal.PtrToStructure((IntPtr)tagPtr, typeof(TIFFTAG));
|
|
||||||
|
|
||||||
switch (tag.u16Tag)
|
|
||||||
{
|
|
||||||
case 273: // StripOffsets...
|
|
||||||
case 279: // StripByteCounts...
|
|
||||||
tiffSize += (int)tag.u32Value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tiffSize > 0)
|
|
||||||
{
|
|
||||||
var dataCopy = new byte[tiffSize];
|
|
||||||
Marshal.Copy(data, dataCopy, 0, tiffSize);
|
|
||||||
|
|
||||||
return Image.FromStream(new MemoryStream(dataCopy));
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts an <see cref="Image"/> to WPF <see cref="BitmapSource"/> if the image
|
|
||||||
/// is a <see cref="Bitmap"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="image">The image to convert.</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static BitmapSource ConvertToWpfBitmap(this Image image)
|
|
||||||
{
|
|
||||||
var bmp = image as Bitmap;
|
|
||||||
if (bmp != null)
|
|
||||||
{
|
|
||||||
using (var hbm = new SafeHBitmapHandle(bmp.GetHbitmap(), true))
|
|
||||||
{
|
|
||||||
return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
|
|
||||||
hbm.DangerousGetHandle(),
|
|
||||||
IntPtr.Zero,
|
|
||||||
System.Windows.Int32Rect.Empty,
|
|
||||||
BitmapSizeOptions.FromEmptyOptions());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
class SafeHBitmapHandle : SafeHandleZeroOrMinusOneIsInvalid
|
|
||||||
{
|
|
||||||
[SecurityCritical]
|
|
||||||
public SafeHBitmapHandle(IntPtr preexistingHandle, bool ownsHandle)
|
|
||||||
: base(ownsHandle)
|
|
||||||
{
|
|
||||||
SetHandle(preexistingHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool ReleaseHandle()
|
|
||||||
{
|
|
||||||
return NativeMethods.DeleteObject(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
138
NTwain/Internals/ImageTools.cs
Normal file
138
NTwain/Internals/ImageTools.cs
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
using NTwain.Interop;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace NTwain.Internals
|
||||||
|
{
|
||||||
|
static class ImageTools
|
||||||
|
{
|
||||||
|
// this is modified from twain cs sample
|
||||||
|
// http://sourceforge.net/projects/twainforcsharp/?source=typ_redirect
|
||||||
|
|
||||||
|
public static bool IsDib(IntPtr data)
|
||||||
|
{
|
||||||
|
// a quick check not guaranteed correct,
|
||||||
|
// compare first 2 bytes to size of struct (which is also the first field)
|
||||||
|
var test = Marshal.ReadInt16(data);
|
||||||
|
// should be 40
|
||||||
|
return test == BITMAPINFOHEADER.GetByteSize();
|
||||||
|
}
|
||||||
|
public static bool IsTiff(IntPtr data)
|
||||||
|
{
|
||||||
|
var test = Marshal.ReadInt16(data);
|
||||||
|
// should be II
|
||||||
|
return test == 0x4949;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Stream GetBitmapStream(IntPtr data)
|
||||||
|
{
|
||||||
|
var infoHeader = (BITMAPINFOHEADER)Marshal.PtrToStructure(data, typeof(BITMAPINFOHEADER));
|
||||||
|
if (infoHeader.Validate())
|
||||||
|
{
|
||||||
|
var fileHeaderSize = Marshal.SizeOf(typeof(BITMAPFILEHEADER));
|
||||||
|
|
||||||
|
|
||||||
|
var fileHeader = new BITMAPFILEHEADER();
|
||||||
|
fileHeader.bfType = 0x4D42; // "BM"
|
||||||
|
fileHeader.bfOffBits = (uint)fileHeaderSize +
|
||||||
|
infoHeader.biSize +
|
||||||
|
(infoHeader.biClrUsed * 4);
|
||||||
|
fileHeader.bfSize = fileHeader.bfOffBits + infoHeader.biSizeImage;
|
||||||
|
|
||||||
|
var dataCopy = new byte[fileHeader.bfSize];
|
||||||
|
// write file header
|
||||||
|
IntPtr tempPtr = Marshal.AllocHGlobal(fileHeaderSize);
|
||||||
|
Marshal.StructureToPtr(fileHeader, tempPtr, true);
|
||||||
|
Marshal.Copy(tempPtr, dataCopy, 0, fileHeaderSize);
|
||||||
|
Marshal.FreeHGlobal(tempPtr);
|
||||||
|
// write image
|
||||||
|
Marshal.Copy(data, dataCopy, fileHeaderSize, (int)fileHeader.bfSize - fileHeaderSize);
|
||||||
|
|
||||||
|
return new MemoryStream(dataCopy);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Stream GetTiffStream(IntPtr data)
|
||||||
|
{
|
||||||
|
// Find the size of the image so we can turn it into a memory stream...
|
||||||
|
var headerSize = Marshal.SizeOf(typeof(TIFFHEADER));
|
||||||
|
var tagSize = Marshal.SizeOf(typeof(TIFFTAG));
|
||||||
|
var tiffSize = 0;
|
||||||
|
var tagPtr = data.ToInt64() + headerSize;
|
||||||
|
for (int i = 0; i < 999; i++)
|
||||||
|
{
|
||||||
|
tagPtr += (tagSize * i);
|
||||||
|
var tag = (TIFFTAG)Marshal.PtrToStructure((IntPtr)tagPtr, typeof(TIFFTAG));
|
||||||
|
|
||||||
|
switch (tag.u16Tag)
|
||||||
|
{
|
||||||
|
case 273: // StripOffsets...
|
||||||
|
case 279: // StripByteCounts...
|
||||||
|
tiffSize += (int)tag.u32Value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tiffSize > 0)
|
||||||
|
{
|
||||||
|
var dataCopy = new byte[tiffSize];
|
||||||
|
// is this optimal?
|
||||||
|
Marshal.Copy(data, dataCopy, 0, tiffSize);
|
||||||
|
return new MemoryStream(dataCopy);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//internal static Bitmap ReadBitmapImage(IntPtr data)
|
||||||
|
//{
|
||||||
|
// Bitmap finalImg = null;
|
||||||
|
// Bitmap tempImg = null;
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// var header = (BITMAPINFOHEADER)Marshal.PtrToStructure(data, typeof(BITMAPINFOHEADER));
|
||||||
|
|
||||||
|
// if (header.Validate())
|
||||||
|
// {
|
||||||
|
// PixelFormat format = header.GetDrawingPixelFormat();
|
||||||
|
// tempImg = new Bitmap(header.biWidth, Math.Abs(header.biHeight), header.GetStride(), format, header.GetScan0(data));
|
||||||
|
// ColorPalette pal = header.GetDrawingPalette(data);
|
||||||
|
// if (pal != null)
|
||||||
|
// {
|
||||||
|
// tempImg.Palette = pal;
|
||||||
|
// }
|
||||||
|
// float xdpi = header.GetXDpi();
|
||||||
|
// float ydpi = header.GetYDpi();
|
||||||
|
// if (xdpi != 0 && ydpi == 0)
|
||||||
|
// {
|
||||||
|
// ydpi = xdpi;
|
||||||
|
// }
|
||||||
|
// else if (ydpi != 0 && xdpi == 0)
|
||||||
|
// {
|
||||||
|
// xdpi = ydpi;
|
||||||
|
// }
|
||||||
|
// if (xdpi != 0)
|
||||||
|
// {
|
||||||
|
// tempImg.SetResolution(xdpi, ydpi);
|
||||||
|
// }
|
||||||
|
// if (header.IsBottomUpImage)
|
||||||
|
// {
|
||||||
|
// tempImg.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
||||||
|
// }
|
||||||
|
// finalImg = tempImg;
|
||||||
|
// tempImg = null;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// finally
|
||||||
|
// {
|
||||||
|
// if (tempImg != null)
|
||||||
|
// {
|
||||||
|
// tempImg.Dispose();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return finalImg;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
@ -330,4 +330,13 @@ namespace NTwain.Interop
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
|
struct BITMAPFILEHEADER
|
||||||
|
{
|
||||||
|
public ushort bfType;
|
||||||
|
public uint bfSize;
|
||||||
|
public ushort bfReserved1;
|
||||||
|
public ushort bfReserved2;
|
||||||
|
public uint bfOffBits;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@
|
|||||||
<Compile Include="DataTransferredEventArgs.cs" />
|
<Compile Include="DataTransferredEventArgs.cs" />
|
||||||
<Compile Include="IMemoryManager.cs" />
|
<Compile Include="IMemoryManager.cs" />
|
||||||
<Compile Include="Internals\ICommittable.cs" />
|
<Compile Include="Internals\ICommittable.cs" />
|
||||||
<Compile Include="ImageTools.cs" />
|
<Compile Include="Internals\ImageTools.cs" />
|
||||||
<Compile Include="Internals\InternalMessageLoopHook.cs" />
|
<Compile Include="Internals\InternalMessageLoopHook.cs" />
|
||||||
<Compile Include="Internals\ITwainSessionInternal.cs" />
|
<Compile Include="Internals\ITwainSessionInternal.cs" />
|
||||||
<Compile Include="Internals\LinuxMemoryManager.cs" />
|
<Compile Include="Internals\LinuxMemoryManager.cs" />
|
||||||
@ -155,6 +155,7 @@
|
|||||||
<Compile Include="Data\TwainValues.cs" />
|
<Compile Include="Data\TwainValues.cs" />
|
||||||
<Compile Include="SourceEnableMode.cs" />
|
<Compile Include="SourceEnableMode.cs" />
|
||||||
<Compile Include="Data\ValueExtensions.cs" />
|
<Compile Include="Data\ValueExtensions.cs" />
|
||||||
|
<Compile Include="WpfImageTools.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="NTwain.nuspec" />
|
<None Include="NTwain.nuspec" />
|
||||||
|
91
NTwain/WpfImageTools.cs
Normal file
91
NTwain/WpfImageTools.cs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
|
||||||
|
namespace NTwain
|
||||||
|
{
|
||||||
|
// this is in its own class to not depend on PresentationCore.dll on mono if it's not used.
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains extension methods for wpf images.
|
||||||
|
/// </summary>
|
||||||
|
public static class WpfImageTools
|
||||||
|
{
|
||||||
|
// <summary>
|
||||||
|
/// Loads a <see cref="Stream" /> into WPF <see cref="BitmapSource" />. The image created
|
||||||
|
/// will be a copy so the stream can be disposed once this call returns.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream">The image stream.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static BitmapSource ConvertToWpfBitmap(this Stream stream)
|
||||||
|
{
|
||||||
|
return ConvertToWpfBitmap(stream, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads a <see cref="Stream" /> into WPF <see cref="BitmapSource" />. The image created
|
||||||
|
/// will be a copy so the stream can be disposed once this call returns.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream">The image stream.</param>
|
||||||
|
/// <param name="decodeWidth">Max width of the decoded image. Pass 0 to use default.</param>
|
||||||
|
/// <param name="decodeHeight">Max height of the decoded image. Pass 0 to use default.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static BitmapSource ConvertToWpfBitmap(this Stream stream, int decodeWidth, int decodeHeight)
|
||||||
|
{
|
||||||
|
if (stream != null)
|
||||||
|
{
|
||||||
|
var image = new BitmapImage();
|
||||||
|
image.BeginInit();
|
||||||
|
image.CacheOption = BitmapCacheOption.OnLoad;
|
||||||
|
image.DecodePixelHeight = decodeHeight;
|
||||||
|
image.DecodePixelWidth = decodeWidth;
|
||||||
|
image.StreamSource = stream;
|
||||||
|
image.EndInit();
|
||||||
|
if (image.CanFreeze)
|
||||||
|
{
|
||||||
|
image.Freeze();
|
||||||
|
}
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///// <summary>
|
||||||
|
///// Converts an <see cref="Image"/> to WPF <see cref="BitmapSource"/> if the image
|
||||||
|
///// is a <see cref="Bitmap"/>.
|
||||||
|
///// </summary>
|
||||||
|
///// <param name="image">The image to convert.</param>
|
||||||
|
///// <returns></returns>
|
||||||
|
//public static BitmapSource ConvertToWpfBitmap(this Image image)
|
||||||
|
//{
|
||||||
|
// var bmp = image as Bitmap;
|
||||||
|
// if (bmp != null)
|
||||||
|
// {
|
||||||
|
// using (var hbm = new SafeHBitmapHandle(bmp.GetHbitmap(), true))
|
||||||
|
// {
|
||||||
|
// return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
|
||||||
|
// hbm.DangerousGetHandle(),
|
||||||
|
// IntPtr.Zero,
|
||||||
|
// System.Windows.Int32Rect.Empty,
|
||||||
|
// BitmapSizeOptions.FromEmptyOptions());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return null;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//class SafeHBitmapHandle : SafeHandleZeroOrMinusOneIsInvalid
|
||||||
|
//{
|
||||||
|
// [SecurityCritical]
|
||||||
|
// public SafeHBitmapHandle(IntPtr preexistingHandle, bool ownsHandle)
|
||||||
|
// : base(ownsHandle)
|
||||||
|
// {
|
||||||
|
// SetHandle(preexistingHandle);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// protected override bool ReleaseHandle()
|
||||||
|
// {
|
||||||
|
// return NativeMethods.DeleteObject(handle);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
13
README.md
13
README.md
@ -45,17 +45,18 @@ session.Open();
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
TwainSession class provides many events, but these 2 are the most important
|
TwainSession class provides many events, but these 3 are the most important
|
||||||
|
|
||||||
* TransferReady - fired before a transfer occurs. You can cancel the current transfer
|
* TransferReady - fired before a transfer occurs. You can cancel the current transfer
|
||||||
or all subsequent transfers using the event object.
|
or all subsequent transfers using the event object.
|
||||||
* DataTransferred - fired after the transfer has occurred. The data available depends on
|
* DataTransferred - fired after the transfer has occurred. The data available depends on
|
||||||
what you've specified using the TWAIN API before starting the transfer. If using image
|
what you've specified using the TWAIN API before starting the transfer. If using image
|
||||||
native transfer, the event arg provides a quick GetNativeImage() method to convert the
|
native transfer, the event arg provides a quick GetNativeImageStream() method to convert the
|
||||||
data to a System.Drawing.Image.
|
data to a System.IO.Stream for use in .net.
|
||||||
|
* TransferError - fired when exceptions are encountered during during the transfer phase.
|
||||||
|
|
||||||
NOTE: do not try to close the source/session in the handler of these 2 events or something
|
NOTE: do not try to close the source/session in the handler of these 3 events or
|
||||||
unpredictable will happen. Either let the scan run its course or cancel the scan using the flag
|
unpredictable things will happen. Either let the scan run its course or cancel the scan using the flag
|
||||||
in the TransferReady event arg.
|
in the TransferReady event arg.
|
||||||
|
|
||||||
Once you've setup and opened the session, you can get available sources, pick one to use,
|
Once you've setup and opened the session, you can get available sources, pick one to use,
|
||||||
@ -140,7 +141,7 @@ session.Close();
|
|||||||
Caveats
|
Caveats
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
At the moment the DataTransferredEventArgs only provides conversion routine to
|
At the moment the DataTransferredEventArgs only provides conversion routine to
|
||||||
an image when using native transfer.
|
an image stream when using native transfer.
|
||||||
If other transfer methods are used you'll have to deal with them yourself.
|
If other transfer methods are used you'll have to deal with them yourself.
|
||||||
|
|
||||||
If you just call session.Open() without passing a message loop hook argument, an
|
If you just call session.Open() without passing a message loop hook argument, an
|
||||||
|
@ -289,22 +289,28 @@ namespace Tester.WPF
|
|||||||
BitmapSource img = null;
|
BitmapSource img = null;
|
||||||
if (e.NativeData != IntPtr.Zero)
|
if (e.NativeData != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
img = e.GetNativeImage().ConvertToWpfBitmap();
|
using (var stream = e.GetNativeImageStream())
|
||||||
|
{
|
||||||
|
if (stream != null)
|
||||||
|
{
|
||||||
|
img = stream.ConvertToWpfBitmap(300, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!string.IsNullOrEmpty(e.FileDataPath))
|
else if (!string.IsNullOrEmpty(e.FileDataPath))
|
||||||
{
|
{
|
||||||
img = new BitmapImage(new Uri(e.FileDataPath));
|
img = new BitmapImage(new Uri(e.FileDataPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (img != null)
|
//if (img != null)
|
||||||
{
|
//{
|
||||||
// from http://stackoverflow.com/questions/18189501/create-thumbnail-image-directly-from-header-less-image-byte-array
|
// // from http://stackoverflow.com/questions/18189501/create-thumbnail-image-directly-from-header-less-image-byte-array
|
||||||
var scale = MaxThumbnailSize / img.PixelWidth;
|
// var scale = MaxThumbnailSize / img.PixelWidth;
|
||||||
var transform = new ScaleTransform(scale, scale);
|
// var transform = new ScaleTransform(scale, scale);
|
||||||
var thumbnail = new TransformedBitmap(img, transform);
|
// var thumbnail = new TransformedBitmap(img, transform);
|
||||||
img = new WriteableBitmap(new TransformedBitmap(img, transform));
|
// img = new WriteableBitmap(new TransformedBitmap(img, transform));
|
||||||
img.Freeze();
|
// img.Freeze();
|
||||||
}
|
//}
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +90,11 @@ namespace Tester.Winform
|
|||||||
Image img = null;
|
Image img = null;
|
||||||
if (e.NativeData != IntPtr.Zero)
|
if (e.NativeData != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
img = e.GetNativeImage();
|
var stream = e.GetNativeImageStream();
|
||||||
|
if (stream != null)
|
||||||
|
{
|
||||||
|
img = Image.FromStream(stream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!string.IsNullOrEmpty(e.FileDataPath))
|
else if (!string.IsNullOrEmpty(e.FileDataPath))
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user