mirror of
https://github.com/soukoku/ntwain.git
synced 2026-02-25 13:04:07 +08:00
Added tiff support.
This commit is contained in:
@@ -124,11 +124,8 @@
|
|||||||
<Compile Include="..\NTwain\Internals\WrappedManualResetEvent.cs">
|
<Compile Include="..\NTwain\Internals\WrappedManualResetEvent.cs">
|
||||||
<Link>Internals\WrappedManualResetEvent.cs</Link>
|
<Link>Internals\WrappedManualResetEvent.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\NTwain\Interop\BITMAPINFO.cs">
|
<Compile Include="..\NTwain\Interop\BITMAP.cs">
|
||||||
<Link>Interop\BITMAPINFO.cs</Link>
|
<Link>Interop\BITMAP.cs</Link>
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\NTwain\Interop\BITMAPINFOHEADER.cs">
|
|
||||||
<Link>Interop\BITMAPINFOHEADER.cs</Link>
|
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\NTwain\Interop\MESSAGE.cs">
|
<Compile Include="..\NTwain\Interop\MESSAGE.cs">
|
||||||
<Link>Interop\MESSAGE.cs</Link>
|
<Link>Interop\MESSAGE.cs</Link>
|
||||||
@@ -136,6 +133,9 @@
|
|||||||
<Compile Include="..\NTwain\Interop\NativeMethods.cs">
|
<Compile Include="..\NTwain\Interop\NativeMethods.cs">
|
||||||
<Link>Interop\NativeMethods.cs</Link>
|
<Link>Interop\NativeMethods.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\NTwain\Interop\TIFF.cs">
|
||||||
|
<Link>Interop\TIFF.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\NTwain\Interop\UnsafeNativeMethods.cs">
|
<Compile Include="..\NTwain\Interop\UnsafeNativeMethods.cs">
|
||||||
<Link>Interop\UnsafeNativeMethods.cs</Link>
|
<Link>Interop\UnsafeNativeMethods.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|||||||
@@ -143,16 +143,16 @@ namespace NTwain
|
|||||||
/// Gets the bitmap from the <see cref="NativeData"/> if it's an image.
|
/// Gets the bitmap from the <see cref="NativeData"/> if it's an image.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Bitmap GetNativeBitmap()
|
public Image GetNativeImage()
|
||||||
{
|
{
|
||||||
Bitmap image = null;
|
Image image = null;
|
||||||
if (NativeData != IntPtr.Zero)
|
if (NativeData != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
if (PlatformInfo.Current.IsWindows)
|
if (ImageTools.IsDib(NativeData))
|
||||||
{
|
{
|
||||||
image = ImageTools.ReadBitmapImage(NativeData);
|
image = ImageTools.ReadBitmapImage(NativeData);
|
||||||
}
|
}
|
||||||
else if (PlatformInfo.Current.IsLinux)
|
else if (ImageTools.IsTiff(NativeData))
|
||||||
{
|
{
|
||||||
image = ImageTools.ReadTiffImage(NativeData);
|
image = ImageTools.ReadTiffImage(NativeData);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Security;
|
using System.Security;
|
||||||
@@ -14,21 +15,33 @@ namespace NTwain
|
|||||||
{
|
{
|
||||||
public static class ImageTools
|
public static class ImageTools
|
||||||
{
|
{
|
||||||
internal static Bitmap ReadBitmapImage(IntPtr dibBitmap)
|
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 finalImg = null;
|
||||||
Bitmap tempImg = null;
|
Bitmap tempImg = null;
|
||||||
if (IsDib(dibBitmap))
|
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var header = (BITMAPINFOHEADER)Marshal.PtrToStructure(dibBitmap, typeof(BITMAPINFOHEADER));
|
var header = (BITMAPINFOHEADER)Marshal.PtrToStructure(data, typeof(BITMAPINFOHEADER));
|
||||||
|
|
||||||
if (header.Validate())
|
if (header.Validate())
|
||||||
{
|
{
|
||||||
PixelFormat format = header.GetDrawingPixelFormat();
|
PixelFormat format = header.GetDrawingPixelFormat();
|
||||||
tempImg = new Bitmap(header.biWidth, Math.Abs(header.biHeight), header.GetStride(), format, header.GetScan0(dibBitmap));
|
tempImg = new Bitmap(header.biWidth, Math.Abs(header.biHeight), header.GetStride(), format, header.GetScan0(data));
|
||||||
ColorPalette pal = header.GetDrawingPalette(dibBitmap);
|
ColorPalette pal = header.GetDrawingPalette(data);
|
||||||
if (pal != null)
|
if (pal != null)
|
||||||
{
|
{
|
||||||
tempImg.Palette = pal;
|
tempImg.Palette = pal;
|
||||||
@@ -62,29 +75,57 @@ namespace NTwain
|
|||||||
tempImg.Dispose();
|
tempImg.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return finalImg;
|
return finalImg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsDib(IntPtr dibBitmap)
|
internal static Image ReadTiffImage(IntPtr data)
|
||||||
{
|
{
|
||||||
// a quick check not guaranteed correct,
|
// this is modified from twain cs sample
|
||||||
// compare first byte to size of struct (which is also the first field)
|
// http://sourceforge.net/projects/twainforcsharp/?source=typ_redirect
|
||||||
var test = Marshal.ReadInt32(dibBitmap);
|
|
||||||
// should be 40
|
|
||||||
return test == BITMAPINFOHEADER.GetByteSize();
|
// 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 header = (TIFFHEADER)Marshal.PtrToStructure(data, typeof(TIFFHEADER));
|
||||||
|
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>
|
/// <summary>
|
||||||
/// Converts a <see cref="Bitmap"/> to WPF <see cref="BitmapSource"/>.
|
/// Converts an <see cref="Image"/> to WPF <see cref="BitmapSource"/> if the image
|
||||||
|
/// is a <see cref="Bitmap"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="image">The image to convert.</param>
|
/// <param name="image">The image to convert.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static BitmapSource ConvertToWpfBitmap(this Bitmap image)
|
public static BitmapSource ConvertToWpfBitmap(this Image image)
|
||||||
{
|
{
|
||||||
if (image != null)
|
var bmp = image as Bitmap;
|
||||||
|
if (bmp != null)
|
||||||
{
|
{
|
||||||
using (var hbm = new SafeHBitmapHandle(image.GetHbitmap(), true))
|
using (var hbm = new SafeHBitmapHandle(bmp.GetHbitmap(), true))
|
||||||
{
|
{
|
||||||
return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
|
return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
|
||||||
hbm.DangerousGetHandle(),
|
hbm.DangerousGetHandle(),
|
||||||
@@ -110,10 +151,5 @@ namespace NTwain
|
|||||||
return NativeMethods.DeleteObject(handle);
|
return NativeMethods.DeleteObject(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static Bitmap ReadTiffImage(IntPtr data)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,34 @@ using System.Text;
|
|||||||
|
|
||||||
namespace NTwain.Interop
|
namespace NTwain.Interop
|
||||||
{
|
{
|
||||||
|
// this is a good read
|
||||||
|
// http://atlc.sourceforge.net/bmp.html
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the dimensions and color information for a DIB.
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
struct BITMAPINFO
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Structure that contains information about the dimensions of color format.
|
||||||
|
/// </summary>
|
||||||
|
public BITMAPINFOHEADER bmiHeader;
|
||||||
|
/// <summary>
|
||||||
|
/// This contains one of the following:
|
||||||
|
/// 1. An array of RGBQUAD. The elements of the array that make up the color table.
|
||||||
|
/// 2. An array of 16-bit unsigned integers that specifies indexes into the currently realized logical palette. This use of bmiColors is allowed for functions that use DIBs.
|
||||||
|
/// The number of entries in the array depends on the values of the biBitCount and biClrUsed members of the BITMAPINFOHEADER structure.
|
||||||
|
/// </summary>
|
||||||
|
public IntPtr bmiColors;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Structure that contains information about the dimensions and color format of a DIB.
|
/// Structure that contains information about the dimensions and color format of a DIB.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct BITMAPINFOHEADER
|
struct BITMAPINFOHEADER
|
||||||
{
|
{
|
||||||
#region fields
|
#region fields
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Drawing.Imaging;
|
|
||||||
using System.Drawing;
|
|
||||||
|
|
||||||
namespace NTwain.Interop
|
|
||||||
{
|
|
||||||
// this is a good read
|
|
||||||
// http://atlc.sourceforge.net/bmp.html
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the dimensions and color information for a DIB.
|
|
||||||
/// </summary>
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct BITMAPINFO
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Structure that contains information about the dimensions of color format.
|
|
||||||
/// </summary>
|
|
||||||
public BITMAPINFOHEADER bmiHeader;
|
|
||||||
/// <summary>
|
|
||||||
/// This contains one of the following:
|
|
||||||
/// 1. An array of RGBQUAD. The elements of the array that make up the color table.
|
|
||||||
/// 2. An array of 16-bit unsigned integers that specifies indexes into the currently realized logical palette. This use of bmiColors is allowed for functions that use DIBs.
|
|
||||||
/// The number of entries in the array depends on the values of the biBitCount and biClrUsed members of the BITMAPINFOHEADER structure.
|
|
||||||
/// </summary>
|
|
||||||
public IntPtr bmiColors;
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
35
NTwain/Interop/TIFF.cs
Normal file
35
NTwain/Interop/TIFF.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NTwain.Interop
|
||||||
|
{
|
||||||
|
// this is from twain cs sample
|
||||||
|
// http://sourceforge.net/projects/twainforcsharp/?source=typ_redirect
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The TIFF file header.
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
|
struct TIFFHEADER
|
||||||
|
{
|
||||||
|
public ushort u8ByteOrder;
|
||||||
|
public ushort u16Version;
|
||||||
|
public uint u32OffsetFirstIFD;
|
||||||
|
public ushort u16u16IFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An individual TIFF Tag.
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
|
struct TIFFTAG
|
||||||
|
{
|
||||||
|
public ushort u16Tag;
|
||||||
|
public ushort u16Type;
|
||||||
|
public uint u32Count;
|
||||||
|
public uint u32Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -70,13 +70,13 @@
|
|||||||
<Compile Include="ImageTools.cs" />
|
<Compile Include="ImageTools.cs" />
|
||||||
<Compile Include="Internals\InternalMessageLoopHook.cs" />
|
<Compile Include="Internals\InternalMessageLoopHook.cs" />
|
||||||
<Compile Include="Internals\ITwainSessionInternal.cs" />
|
<Compile Include="Internals\ITwainSessionInternal.cs" />
|
||||||
<Compile Include="Interop\BITMAPINFO.cs" />
|
<Compile Include="Interop\BITMAP.cs" />
|
||||||
<Compile Include="Interop\BITMAPINFOHEADER.cs" />
|
|
||||||
<Compile Include="Interop\MESSAGE.cs" />
|
<Compile Include="Interop\MESSAGE.cs" />
|
||||||
<Compile Include="Internals\TransferLogic.cs" />
|
<Compile Include="Internals\TransferLogic.cs" />
|
||||||
<Compile Include="Internals\WindowsHook.cs" />
|
<Compile Include="Internals\WindowsHook.cs" />
|
||||||
<Compile Include="Internals\WrappedManualResetEvent.cs" />
|
<Compile Include="Internals\WrappedManualResetEvent.cs" />
|
||||||
<Compile Include="Interop\NativeMethods.cs" />
|
<Compile Include="Interop\NativeMethods.cs" />
|
||||||
|
<Compile Include="Interop\TIFF.cs" />
|
||||||
<Compile Include="IPlatformInfo.cs" />
|
<Compile Include="IPlatformInfo.cs" />
|
||||||
<Compile Include="ITripletControl.cs" />
|
<Compile Include="ITripletControl.cs" />
|
||||||
<Compile Include="ITwainSession.cs" />
|
<Compile Include="ITwainSession.cs" />
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ TwainSession class provides many events, but these 2 are the most important
|
|||||||
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 GetNativeBitmap() method to convert the
|
native transfer, the event arg provides a quick GetNativeImage() method to convert the
|
||||||
data to a System.Drawing.Bitmap.
|
data to a System.Drawing.Image.
|
||||||
|
|
||||||
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 2 events or something
|
||||||
unpredictable will happen. Either let the scan run its course or cancel the scan using the flag
|
unpredictable will happen. Either let the scan run its course or cancel the scan using the flag
|
||||||
@@ -140,7 +140,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
|
||||||
a Bitmap image when using native transfer.
|
an image 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,7 +289,7 @@ namespace Tester.WPF
|
|||||||
BitmapSource img = null;
|
BitmapSource img = null;
|
||||||
if (e.NativeData != IntPtr.Zero)
|
if (e.NativeData != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
img = e.GetNativeBitmap().ConvertToWpfBitmap();
|
img = e.GetNativeImage().ConvertToWpfBitmap();
|
||||||
}
|
}
|
||||||
else if (!string.IsNullOrEmpty(e.FileDataPath))
|
else if (!string.IsNullOrEmpty(e.FileDataPath))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -87,10 +87,10 @@ namespace Tester.Winform
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle image data
|
// handle image data
|
||||||
Bitmap img = null;
|
Image img = null;
|
||||||
if (e.NativeData != IntPtr.Zero)
|
if (e.NativeData != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
img = e.GetNativeBitmap();
|
img = e.GetNativeImage();
|
||||||
}
|
}
|
||||||
else if (!string.IsNullOrEmpty(e.FileDataPath))
|
else if (!string.IsNullOrEmpty(e.FileDataPath))
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user