I use LeadTools for scanning.
I want to convert scanning image to byte.
void twainSession_AcquirePage(object sender, TwainAcquirePageEventArgs e)
{
I ran into this issue in Xamarin.Forms where I needed to convert a taken photo from the camera into a Byte array. After spending days trying to find out how, I saw this solution in the Xamarin forums.
var photo = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions() { });
byte[] imageArray = null;
using (MemoryStream memory = new MemoryStream()) {
Stream stream = photo.GetStream();
stream.CopyTo(memory);
imageArray = memory.ToArray();
}
Source: https://forums.xamarin.com/discussion/156236/how-to-get-the-bytes-from-the-imagesource-in-xamarin-forms
It seems that you can cast the result from .ConvertToSource to a BitmapSource instead of a ImageSource.
I am not 100% sure how this translate to your case but the doc from LeadTools show this VB sample:
Dim source As BitmapSource
Using raster As RasterImage = RasterImageConverter.ConvertFromSource(bitmap, ConvertFromSourceOptions.None)
Console.WriteLine("Converted to RasterImage, bits/pixel is {0} and order is {1}", raster.BitsPerPixel, raster.Order)
' Perform image processing on the raster image using LEADTOOLS
Dim cmd As New FlipCommand(False)
cmd.Run(raster)
' Convert the image back to WPF using default options
source = DirectCast(RasterImageConverter.ConvertToSource(raster, ConvertToSourceOptions.None), BitmapSource)
End Using
I think it should be like
BitmapSource source = RasterImageConverter.ConvertToSource(ScanImage, ConvertToSourceOptions.None) as BitmapSource;
Then you can copy the BitmapSource pixels with BitmapSource.CopyPixels
If you are using Xamarin, you can use this:
public byte[] ImageSourceToBytes(ImageSource imageSource)
{
StreamImageSource streamImageSource = (StreamImageSource)imageSource;
System.Threading.CancellationToken cancellationToken =
System.Threading.CancellationToken.None;
Task<Stream> task = streamImageSource.Stream(cancellationToken);
Stream stream = task.Result;
byte[] bytesAvailable = new byte[stream.Length];
stream.Read(bytesAvailable, 0, bytesAvailable.Length);
return bytesAvailable;
}
I use use a MemoryStream:
var source = RasterImageConverter.ConvertToSource(ScanImage, ConvertToSourceOptions.None) as BitmapSource;
byte[] data;
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(source));
using (MemoryStream ms = new MemoryStream())
{
encoder.Save(ms);
data = ms.ToArray();
}
I use this class to work with Image
in WPF
public static class ImageHelper
{
/// <summary>
/// ImageSource to bytes
/// </summary>
/// <param name="encoder"></param>
/// <param name="imageSource"></param>
/// <returns></returns>
public static byte[] ImageSourceToBytes(BitmapEncoder encoder, ImageSource imageSource)
{
byte[] bytes = null;
var bitmapSource = imageSource as BitmapSource;
if (bitmapSource != null)
{
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
using (var stream = new MemoryStream())
{
encoder.Save(stream);
bytes = stream.ToArray();
}
}
return bytes;
}
[DllImport("gdi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool DeleteObject(IntPtr value);
public static BitmapSource GetImageStream(Image myImage)
{
var bitmap = new Bitmap(myImage);
IntPtr bmpPt = bitmap.GetHbitmap();
BitmapSource bitmapSource =
System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
bmpPt,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
//freeze bitmapSource and clear memory to avoid memory leaks
bitmapSource.Freeze();
DeleteObject(bmpPt);
return bitmapSource;
}
/// <summary>
/// Convert String to ImageFormat
/// </summary>
/// <param name="format"></param>
/// <returns></returns>
public static System.Drawing.Imaging.ImageFormat ImageFormatFromString(string format)
{
if (format.Equals("Jpg"))
format = "Jpeg";
Type type = typeof(System.Drawing.Imaging.ImageFormat);
BindingFlags flags = BindingFlags.GetProperty;
object o = type.InvokeMember(format, flags, null, type, null);
return (System.Drawing.Imaging.ImageFormat)o;
}
/// <summary>
/// Read image from path
/// </summary>
/// <param name="imageFile"></param>
/// <param name="imageFormat"></param>
/// <returns></returns>
public static byte[] BytesFromImage(String imageFile, System.Drawing.Imaging.ImageFormat imageFormat)
{
MemoryStream ms = new MemoryStream();
Image img = Image.FromFile(imageFile);
img.Save(ms, imageFormat);
return ms.ToArray();
}
/// <summary>
/// Convert image to byte array
/// </summary>
/// <param name="imageIn"></param>
/// <param name="imageFormat"></param>
/// <returns></returns>
public static byte[] ImageToByteArray(System.Drawing.Image imageIn, System.Drawing.Imaging.ImageFormat imageFormat)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, imageFormat);
return ms.ToArray();
}
/// <summary>
/// Byte array to photo
/// </summary>
/// <param name="byteArrayIn"></param>
/// <returns></returns>
public static Image ByteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
}
So try different approaches and modernize this class as you need.
Unless you explicitly need an ImageSource object, there's no need to convert to one. You can get a byte array containing the pixel data directly from Leadtools.RasterImage using this code:
int totalPixelBytes = e.Image.BytesPerLine * e.Image.Height;
byte[] byteArray = new byte[totalPixelBytes];
e.Image.GetRow(0, byteArray, 0, totalPixelBytes);
Note that this gives you only the raw pixel data.
If you need a memory stream or byte array that contains a complete image such as JPEG, you also do not need to convert to source. You can use the Leadtools.RasterCodecs class like this:
RasterCodecs codecs = new RasterCodecs();
System.IO.MemoryStream memStream = new System.IO.MemoryStream();
codecs.Save(e.Image, memStream, RasterImageFormat.Jpeg, 24);