Added tiff support.

This commit is contained in:
soukoku
2015-02-18 21:06:07 -05:00
parent b27a9ba4cc
commit daaeb840af
10 changed files with 166 additions and 104 deletions

View File

@@ -143,16 +143,16 @@ namespace NTwain
/// Gets the bitmap from the <see cref="NativeData"/> if it's an image.
/// </summary>
/// <returns></returns>
public Bitmap GetNativeBitmap()
public Image GetNativeImage()
{
Bitmap image = null;
Image image = null;
if (NativeData != IntPtr.Zero)
{
if (PlatformInfo.Current.IsWindows)
if (ImageTools.IsDib(NativeData))
{
image = ImageTools.ReadBitmapImage(NativeData);
}
else if (PlatformInfo.Current.IsLinux)
else if (ImageTools.IsTiff(NativeData))
{
image = ImageTools.ReadTiffImage(NativeData);
}

View File

@@ -4,6 +4,7 @@ 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;
@@ -14,77 +15,117 @@ namespace NTwain
{
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 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())
{
PixelFormat format = header.GetDrawingPixelFormat();
tempImg = new Bitmap(header.biWidth, Math.Abs(header.biHeight), header.GetStride(), format, header.GetScan0(dibBitmap));
ColorPalette pal = header.GetDrawingPalette(dibBitmap);
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 (header.Validate())
{
if (tempImg != null)
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.Dispose();
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;
}
static bool IsDib(IntPtr dibBitmap)
internal static Image ReadTiffImage(IntPtr data)
{
// a quick check not guaranteed correct,
// compare first byte to size of struct (which is also the first field)
var test = Marshal.ReadInt32(dibBitmap);
// should be 40
return test == BITMAPINFOHEADER.GetByteSize();
// 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 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>
/// 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>
/// <param name="image">The image to convert.</param>
/// <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(
hbm.DangerousGetHandle(),
@@ -110,10 +151,5 @@ namespace NTwain
return NativeMethods.DeleteObject(handle);
}
}
internal static Bitmap ReadTiffImage(IntPtr data)
{
return null;
}
}
}

View File

@@ -7,11 +7,34 @@ using System.Text;
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>
/// Structure that contains information about the dimensions and color format of a DIB.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct BITMAPINFOHEADER
struct BITMAPINFOHEADER
{
#region fields
/// <summary>

View File

@@ -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
View 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;
}
}

View File

@@ -70,13 +70,13 @@
<Compile Include="ImageTools.cs" />
<Compile Include="Internals\InternalMessageLoopHook.cs" />
<Compile Include="Internals\ITwainSessionInternal.cs" />
<Compile Include="Interop\BITMAPINFO.cs" />
<Compile Include="Interop\BITMAPINFOHEADER.cs" />
<Compile Include="Interop\BITMAP.cs" />
<Compile Include="Interop\MESSAGE.cs" />
<Compile Include="Internals\TransferLogic.cs" />
<Compile Include="Internals\WindowsHook.cs" />
<Compile Include="Internals\WrappedManualResetEvent.cs" />
<Compile Include="Interop\NativeMethods.cs" />
<Compile Include="Interop\TIFF.cs" />
<Compile Include="IPlatformInfo.cs" />
<Compile Include="ITripletControl.cs" />
<Compile Include="ITwainSession.cs" />