Fingerprint byte array to Imagesource in WPF - c#

I am trying to convert fingerprint byte array to imagesource in the WPF application but my tricks not working.
Here is the code :
byte[] fp_image; //fp_image contains the fingerprint byte array result
using (MemoryStream ms = new MemoryStream(fp_image))
{
Bitmap bmp = new Bitmap(ms);
FpImage.Source = ConvertToImageSource(bmp);
}
public static ImageSource ConvertToImageSource(Bitmap bitmap)
{
var imageSourceConverter = new ImageSourceConverter();
using (var memoryStream = new MemoryStream())
{
bitmap.Save(memoryStream, ImageFormat.Png);
var snapshotBytes = memoryStream.ToArray();
return (ImageSource)imageSourceConverter.ConvertFrom(snapshotBytes); ;
}
}
Note : If I convert any other image to byte array and convert it back to image with this code it's working.

Assuming byte[] fp_image contains raw data then you could directly create a BitmapSource (which is a subclass of ImageSource) with the method shown below. However, you need to know the width, height and pixel format of the bitmap in your buffer.
public BitmapSource GetBitmapFromRawBytes(
byte[] rawBytes, int width, int height, PixelFormat format)
{
var stride = (width * format.BitsPerPixel + 7) / 8;
return BitmapSource.Create(width, height, 96, 96, format, null, rawBytes, stride);
}

Related

Converting a System.Windows.Media.Drawing object to Bitmap bytes

I have a System.Windows.Media.Drawing object that I am wanting to convert into a Bitmap object, and then from there extract the bytes that represent the image. I've looked about the internet and I can't seem to find how to do what I need, so any help would be appreciated.
So I finally found a way to convert a System.Windows.Media.Drawing object to a System.Drawing.Bitmap object, and from that get a byte[] object representing the image data. The following is not pretty but does actually work.
public static byte[] DrawingToBytes(Drawing drawing)
{
DrawingVisual visual = new DrawingVisual();
using (DrawingContext context = visual.RenderOpen())
{
// If using the BitmapEncoder uncomment the following line to get a white background.
// context.DrawRectangle(Brushes.White, null, drawing.bounds);
context.DrawDrawing(drawing);
}
int width = (int)(drawing.Bounds.Width)
int height = (int)(drawing.Bounds.Height)
Bitmap bmp = new Bitmap(width, height);
Bitmap bmpOut;
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(System.Drawing.Color.White);
RenderTargetBitmap rtBmp = new RenderTargetBitmap(width, height,
bmp.HorizontalResolution,
bmp.VerticalResolution,
PixelFormats.Pbgra32);
rtBmp.Render(visual);
// Alternative using BmpBitmapEncoder, use in place of what comes after if you wish.
// MemoryStream stream = new MemoryStream();
// BitmapEncoder encoder = new BmpBitmapEncoder();
// encoder.Frames.Add(BitmapFrame.Create(rtBmp));
// encoder.save(stream);
int stride = width * ((rtBmp.Format.BitsPerPixel + 7) / 8);
byte[] bits = new byte[height * stride];
bitmapSource.CopyPixels(bits, stride, 0);
unsafe
{
fixed (byte* pBits = bits)
{
IntPtr ptr = new IntPtr(pBits);
bmpOut = new Bitmap(width, height, stride,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb, ptr);
}
}
g.DrawImage(bmpOut, 0, 0, bmp.Width, bmp.Height);
}
byte[] bytes;
using (MemoryStream ms = new MemoryStream())
{
bmp.Save(ms, ImageFormat.bmp);
data = ms.ToArray();
}
return bytes;
}
So yeah, it's horrible but it actually works.
You can try that:
byte[] ImageToByte(Image image)
{
ImageConverter converter = new ImageConverter();
return (byte[])converter.ConvertTo(img, typeof(byte[]));
}
This work also for Bitmap.

How to convert pixel byte array to bitmap image in windows phone 8

I want to draw Image in windows phone 8 using pixel byte. so I get some pixel byte via c++ library(c++/CLI). But pixel data not include bitmap Header. It is just pixel byte array.
Is this possible to convert pixel data array to bitmap Image without bitmap header in windows phone?
public void updateImage(byte[] byteArray, UInt32 bufferSize, int cvtWidth, int cvtHeight)
{
// I saw this source a lot of search. But It's not work. It makes some exeption.
BitmapImage bi = new BitmapImage();
MemoryStream memoryStream = new MemoryStream(byteArray);
bi.SetSource(memoryStream);
ImageScreen.Source = bi;
}
You need to use a WriteableBitmap : http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.media.imaging.writeablebitmap
Then you can access it's PixelBuffer using AsStream and save that array to the stream.
//srcWidth and srcHeight are original image size, needed
//srcData is pixel data array
WriteableBitmap wb = new WriteableBitmap(srcWidth, srcHeight);
using (Stream stream = wb.PixelBuffer.AsStream())
{
await stream.WriteAsync(srcData, 0, srcData.Length);
}
EDIT
As Proglamour stated in WIndows Phone there is no PixelBuffer, but a property named Pixels which is an array exists.
It cannot be replaced but it's content can so this should work:
WriteableBitmap wb = new WriteableBitmap(srcWidth, srcHeight);
Array.Copy(srcData, wb.Pixels, srcData.Length);
I solved this problem. Thanks for your help Filip.
public void updateImage(byte[] byteArray, UInt32 bufferSize, int cvtWidth, int cvtHeight)
{
Dispatcher.BeginInvoke(() =>
{
WriteableBitmap wb = new WriteableBitmap(cvtWidth, cvtHeight);
System.Buffer.BlockCopy(byteArray, 0, wb.Pixels, 0, byteArray.Length);
//wb.Invalidate();
ImageScreen.Source = wb;
});
}

Win8 App Store - How to get PixelFormat?

In Win8 App Store, given a stream, how can I get the PixelFormat of the image from that stream? I can only get byte array, width, height, stride but I also need pixel format type (like how many bits per pixel, rgba32...) to create some kind of BitmapSource:
//Copy photo from camera to stream
var fPhotoStream = new InMemoryRandomAccessStream();
await mediaCaptureMgr.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), fPhotoStream);
await fPhotoStream.FlushAsync();
fPhotoStream.Seek(0);
//Convert stream to byte array
byte[] bytes = new byte[fPhotoStream.Size];
await fPhotoStream.ReadAsync(bytes.AsBuffer(), (uint)fPhotoStream.Size, InputStreamOptions.None);
//Get pointer to byte array
GCHandle pinnedArray = GCHandle.Alloc(bytes, GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
//Get image width, height, stride
BitmapImage bmp = new BitmapImage();
bmp.SetSource(fPhotoStream);
int imgWidth = bmp.PixelWidth;
int imgHeight = bmp.PixelHeight;
int stride = bmp.Width * 4;
//But how to get image pixel format?
int pixelFormat = ??????
Can I do that?
I found that I can use BitmapDecoder to get the PixelFormat information:
http://msdn.microsoft.com/en-us/library/windows/apps/jj709939.aspx

How to Convert System.Windows.Media.Imaging.BitmapImage to System.Drawing.Image?

The XAML:
<ImageBrush x:Key="Symbol1Brush" ImageSource="Resources\Symbol1.png" Stretch="Uniform" />
The code:
// In some class
_imageProcessor = new ImageProcessor(Resources["Symbol1Image"] as BitmapImage)
and
public class ImageProcessor
{
private readonly Bitmap _primaryMarkerSymbol;
public ImageProcessor(BitmapImage primaryMarkerSymbol)
{
if (primaryMarkerSymbol == null)
throw new ArgumentNullException("primaryMarkerSymbol");
_primaryMarkerSymbol = new Bitmap(primaryMarkerSymbol.StreamSource);
}
public Bitmap ProcessImage()
{
Graphics g = Graphics.FromImage(img);
g.DrawImage(_primaryMarkerSymbol);
g.Flush();
return img;
}
}
_primaryMarkerSymbol = new Bitmap(primaryMarkerSymbol.StreamSource)
throws Exception: Value of 'null' is not valid for 'stream'.
I assume the StreamSource is not populated if BitmapImage is created from Resource.
What alternatives there are?
Thanks.
EDIT:
The point is to use the source object (ex. ImageBrush, BitmapImage) defined in the XAML ResourceDictionary.
You might need to copy the bitmap's pixels somehow like this:
// test image
BitmapImage image = new BitmapImage(new Uri(#"C:\Users\Public\Pictures\Sample Pictures\Desert.jpg"));
// copy to byte array
int stride = image.PixelWidth * 4;
byte[] buffer = new byte[stride * image.PixelHeight];
image.CopyPixels(buffer, stride, 0);
// create bitmap
System.Drawing.Bitmap bitmap =
new System.Drawing.Bitmap(
image.PixelWidth,
image.PixelHeight,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
// lock bitmap data
System.Drawing.Imaging.BitmapData bitmapData =
bitmap.LockBits(
new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
System.Drawing.Imaging.ImageLockMode.WriteOnly,
bitmap.PixelFormat);
// copy byte array to bitmap data
System.Runtime.InteropServices.Marshal.Copy(
buffer, 0, bitmapData.Scan0, buffer.Length);
// unlock
bitmap.UnlockBits(bitmapData);
This worked for me to set an image source using resource files
var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(MyProject.Properties.Resources.myImage.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
MyButton.Background = new ImageBrush(bitmapSource);
In the constructor, I would rather use this:
System.Windows.Resources.StreamResourceInfo imageInfo = System.Windows.Application.GetResourceStream(primaryMarkerSymbol.UriSource);
_primaryMarkerSymbol = Image.FromStream(imageInfo.Stream);
On a clear moment I have come up with a solution that I could saddle with.
I used the BitmapImage.UriSource to get the relative image path and load the Image:
public class ImageProcessor
{
private readonly Image _primaryMarkerSymbol;
public ImageProcessor(BitmapImage primaryMarkerSymbol)
{
_primaryMarkerSymbol = Image.FromFile(primaryMarkerSymbol.UriSource.ToString());
}
public Bitmap ProcessImage(string fileName)
{
var img = new Bitmap(fileName);
Graphics g = Graphics.FromImage(img);
g.DrawImage(_primaryMarkerSymbol);
g.Flush();
return img;
}
}
It would be good if I could use the object itself to draw the image on the graphics not to load by path. So you are welcome to come up with a better idea.

Byte array to image conversion

I want to convert a byte array to an image.
This is my database code from where I get the byte array:
public void Get_Finger_print()
{
try
{
using (SqlConnection thisConnection = new SqlConnection(#"Data Source=" + System.Environment.MachineName + "\\SQLEXPRESS;Initial Catalog=Image_Scanning;Integrated Security=SSPI "))
{
thisConnection.Open();
string query = "select pic from Image_tbl";// where Name='" + name + "'";
SqlCommand cmd = new SqlCommand(query, thisConnection);
byte[] image =(byte[]) cmd.ExecuteScalar();
Image newImage = byteArrayToImage(image);
Picture.Image = newImage;
//return image;
}
}
catch (Exception) { }
//return null;
}
My conversion code:
public Image byteArrayToImage(byte[] byteArrayIn)
{
try
{
MemoryStream ms = new MemoryStream(byteArrayIn,0,byteArrayIn.Length);
ms.Write(byteArrayIn, 0, byteArrayIn.Length);
returnImage = Image.FromStream(ms,true);//Exception occurs here
}
catch { }
return returnImage;
}
When I reach the line with a comment, the following exception occurs: Parameter is not valid.
How can I fix whatever is causing this exception?
You are writing to your memory stream twice, also you are not disposing the stream after use.
You are also asking the image decoder to apply embedded color correction.
Try this instead:
using (var ms = new MemoryStream(byteArrayIn))
{
return Image.FromStream(ms);
}
Maybe I'm missing something, but for me this one-liner works fine with a byte array that contains an image of a JPEG file.
Image x = (Bitmap)((new ImageConverter()).ConvertFrom(jpegByteArray));
EDIT:
See here for an updated version of this answer: How to convert image in byte array
public Image byteArrayToImage(byte[] bytesArr)
{
using (MemoryStream memstr = new MemoryStream(bytesArr))
{
Image img = Image.FromStream(memstr);
return img;
}
}
I'd like to note there is a bug in solution provided by #isaias-b.
That solution assume that stride is equal to row length. But it is not always true. Due to memory alignments performed by GDI, stride can be greater then row length. This must be taken into account. Otherwise invalid shifted image will be generated. Padding bytes in each row will be ignored.
The stride is the width of a single row of pixels (a scan line), rounded up to a four-byte boundary.
Fixed code:
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
public static class ImageExtensions
{
public static Image ImageFromRawBgraArray(this byte[] arr, int width, int height, PixelFormat pixelFormat)
{
var output = new Bitmap(width, height, pixelFormat);
var rect = new Rectangle(0, 0, width, height);
var bmpData = output.LockBits(rect, ImageLockMode.ReadWrite, output.PixelFormat);
// Row-by-row copy
var arrRowLength = width * Image.GetPixelFormatSize(output.PixelFormat) / 8;
var ptr = bmpData.Scan0;
for (var i = 0; i < height; i++)
{
Marshal.Copy(arr, i * arrRowLength, ptr, arrRowLength);
ptr += bmpData.Stride;
}
output.UnlockBits(bmpData);
return output;
}
}
To illustrate what it can lead to, let's generate PixelFormat.Format24bppRgb gradient image 101x101:
var width = 101;
var height = 101;
var gradient = new byte[width * height * 3 /* bytes per pixel */];
for (int i = 0, pixel = 0; i < gradient.Length; i++, pixel = i / 3)
{
var x = pixel % height;
var y = (pixel - x) / width;
gradient[i] = (byte)((x / (double)(width - 1) + y / (double)(height - 1)) / 2d * 255);
}
If we will copy entire array as-is to address pointed by bmpData.Scan0, we will get following image. Image shifting because part of image was written to padding bytes, that was ignored. Also that is why last row is incomplete:
But if we will copy row-by-row shifting destination pointer by bmpData.Stride value, valid imaged will be generated:
Stride also can be negative:
If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up.
But I didn't worked with such images and this is beyond my note.
Related answer: C# - RGB Buffer from Bitmap different from C++
All presented answers assume that the byte array contains data in a known file format representation, like: gif, png or jpg. But i recently had a problem trying to convert byte[]s, containing linearized BGRA information, efficiently into Image objects. The following code solves it using a Bitmap object.
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
public static class Extensions
{
public static Image ImageFromRawBgraArray(
this byte[] arr, int width, int height)
{
var output = new Bitmap(width, height);
var rect = new Rectangle(0, 0, width, height);
var bmpData = output.LockBits(rect,
ImageLockMode.ReadWrite, output.PixelFormat);
var ptr = bmpData.Scan0;
Marshal.Copy(arr, 0, ptr, arr.Length);
output.UnlockBits(bmpData);
return output;
}
}
This is a slightly variation of a solution which was posted on this site.
In one line:
Image.FromStream(new MemoryStream(byteArrayIn));
try (UPDATE)
MemoryStream ms = new MemoryStream(byteArrayIn,0,byteArrayIn.Length);
ms.Position = 0; // this is important
returnImage = Image.FromStream(ms,true);
there is a simple approach as below, you can use FromStream method of an image to do the trick,
Just remember to use System.Drawing;
// using image object not file
public byte[] imageToByteArray(Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms,System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
public Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
One liner:
Image bmp = (Bitmap)((new ImageConverter()).ConvertFrom(imageBytes));
You haven't declared returnImage as any kind of variable :)
This should help:
public Image byteArrayToImage(byte[] byteArrayIn)
{
try
{
MemoryStream ms = new MemoryStream(byteArrayIn,0,byteArrayIn.Length);
ms.Write(byteArrayIn, 0, byteArrayIn.Length);
Image returnImage = Image.FromStream(ms,true);
}
catch { }
return returnImage;
}
This is inspired by Holstebroe's answer, plus comments here: Getting an Image object from a byte array
Bitmap newBitmap;
using (MemoryStream memoryStream = new MemoryStream(byteArrayIn))
using (Image newImage = Image.FromStream(memoryStream))
newBitmap = new Bitmap(newImage);
return newBitmap;
Most of the time when this happens it is bad data in the SQL column. This is the proper way to insert into an image column:
INSERT INTO [TableX] (ImgColumn) VALUES (
(SELECT * FROM OPENROWSET(BULK N'C:\....\Picture 010.png', SINGLE_BLOB) as tempimg))
Most people do it incorrectly this way:
INSERT INTO [TableX] (ImgColumn) VALUES ('C:\....\Picture 010.png'))
First Install This Package:
Install-Package SixLabors.ImageSharp -Version 1.0.0-beta0007
[SixLabors.ImageSharp][1]
[1]: https://www.nuget.org/packages/SixLabors.ImageSharp
Then use Below Code For Cast Byte Array To Image :
Image<Rgba32> image = Image.Load(byteArray);
For Get ImageFormat Use Below Code:
IImageFormat format = Image.DetectFormat(byteArray);
For Mutate Image Use Below Code:
image.Mutate(x => x.Resize(new Size(1280, 960)));
I suggest using ImageSharp
Image<Bgra32> image = SixLabors.ImageSharp.Image.LoadPixelData<Bgra32>
(byteArray
, pageWidth
, pageHeight);

Categories

Resources