Byte array to image conversion

C#ArraysByteBytebuffer

C# Problem Overview


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?

C# Solutions


Solution 1 - C#

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);
}

Solution 2 - C#

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: https://stackoverflow.com/questions/3801275/how-to-convert-image-in-byte-array/16576471#16576471

Solution 3 - C#

public Image byteArrayToImage(byte[] bytesArr)
{
    using (MemoryStream memstr = new MemoryStream(bytesArr))
    {
        Image img = Image.FromStream(memstr);
        return img;
    }
}

Solution 4 - C#

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:

stride ignored

But if we will copy row-by-row shifting destination pointer by bmpData.Stride value, valid imaged will be generated:

stride taken into account

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: https://stackoverflow.com/questions/26167971/c-sharp-rgb-buffer-from-bitmap-different-from-c/40356510#40356510

Solution 5 - 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.

Solution 6 - C#

try (UPDATE)

MemoryStream ms = new MemoryStream(byteArrayIn,0,byteArrayIn.Length);
ms.Position = 0; // this is important
returnImage = Image.FromStream(ms,true);

Solution 7 - C#

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

Solution 8 - C#

In one line:

Image.FromStream(new MemoryStream(byteArrayIn));

Solution 9 - C#

This is inspired by Holstebroe's answer, plus comments here: https://stackoverflow.com/questions/3290060/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;

Solution 10 - C#

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

Solution 11 - C#

One liner:

Image bmp = (Bitmap)((new ImageConverter()).ConvertFrom(imageBytes));

Solution 12 - C#

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'))

Solution 13 - C#

> 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)));

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTanzeel ur RahmanView Question on Stackoverflow
Solution 1 - C#HolstebroeView Answer on Stackoverflow
Solution 2 - C#RenniePetView Answer on Stackoverflow
Solution 3 - C#Ali GhView Answer on Stackoverflow
Solution 4 - C#lorondView Answer on Stackoverflow
Solution 5 - C#isaias-bView Answer on Stackoverflow
Solution 6 - C#YahiaView Answer on Stackoverflow
Solution 7 - C#AliView Answer on Stackoverflow
Solution 8 - C#TiyebMView Answer on Stackoverflow
Solution 9 - C#RenniePetView Answer on Stackoverflow
Solution 10 - C#LeeCamblView Answer on Stackoverflow
Solution 11 - C#Vinnie AmirView Answer on Stackoverflow
Solution 12 - C#GPGVMView Answer on Stackoverflow
Solution 13 - C#Amin GolmahalleView Answer on Stackoverflow