Преобразование байтового массива в изображение - PullRequest
82 голосов
/ 07 февраля 2012

Я хочу преобразовать байтовый массив в изображение.

Это код моей базы данных, откуда я получаю байтовый массив:

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

Мой код преобразования:

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

Когда я достигаю строки с комментарием, возникает следующее исключение: Parameter is not valid.

Как я могу исправить то, что вызывает это исключение?

Ответы [ 11 ]

98 голосов
/ 07 февраля 2012

Вы дважды записываете в свой поток памяти, а также не утилизируете поток после использования. Вы также просите декодер изображений применить встроенную коррекцию цвета.

Попробуйте вместо этого:

using (var ms = new MemoryStream(byteArrayIn))
{
    return Image.FromStream(ms);
}
75 голосов
/ 03 февраля 2013

Может быть, я что-то упустил, но для меня этот однострочный отлично работает с байтовым массивом, который содержит изображение файла JPEG.

Image x = (Bitmap)((new ImageConverter()).ConvertFrom(jpegByteArray));

РЕДАКТИРОВАТЬ:

См.здесь для обновленной версии этого ответа: Как преобразовать изображение в байтовый массив

11 голосов
/ 05 января 2015
    public Image byteArrayToImage(byte[] bytesArr)
    {
        using (MemoryStream memstr = new MemoryStream(bytesArr))
        {
            Image img = Image.FromStream(memstr);
            return img;
        }
    }
7 голосов
/ 22 июля 2016

Хочу отметить, что в решении, предоставленном @ isaias-b, есть ошибка.

В этом решении предполагается, что stride равно длине строки.Но это не всегда так.Из-за выравнивания памяти, выполняемого GDI, шаг может быть больше, чем длина строки.Это необходимо учитывать.В противном случае будет сгенерировано неверное смещенное изображение.Байты заполнения в каждой строке будут игнорироваться.

Шаг - это ширина одного ряда пикселей (строки развертки), округленная до четырехбайтовой границы.

Фиксированный код:

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

Чтобы проиллюстрировать, к чему это может привести, давайте сгенерируем PixelFormat.Format24bppRgb градиентное изображение 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);
}

Если мы скопируем весь массив как естьпо адресу, указанному bmpData.Scan0, мы получим следующее изображение.Смещение изображения, потому что часть изображения была записана в байты заполнения, что было проигнорировано.Также, поэтому последняя строка является неполной:

stride ignored

Но если мы будем копировать строковый указатель смещения по строке на значение bmpData.Stride, допустимобудет сгенерировано изображение:

stride taken into account

Шаг также может быть отрицательным:

Если шаг является положительным, битовая картанизходящий.Если шаг отрицательный, растровое изображение идет снизу вверх.

Но я не работал с такими изображениями, и это выходит за рамки моей заметки.

Соответствующий ответ: C # - RGB-буфер из Bitmap, отличный от C ++

6 голосов
/ 27 января 2018

есть простой подход, как показано ниже, вы можете использовать FromStream метод изображения, чтобы сделать трюк, Просто не забудьте использовать 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;
}
5 голосов
/ 20 июня 2014

Все представленные ответы предполагают, что байтовый массив содержит данные в представлении известного формата файла, например: gif, png или jpg.Но недавно у меня возникла проблема с попыткой эффективно преобразовать byte[] s, содержащий линеаризованную информацию BGRA, в Image объекты.Следующий код решает его с помощью объекта Bitmap.

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

Это небольшое изменение решения, которое было размещено на этом сайте .

5 голосов
/ 07 февраля 2012

попытка (ОБНОВЛЕНИЕ)

MemoryStream ms = new MemoryStream(byteArrayIn,0,byteArrayIn.Length);
ms.Position = 0; // this is important
returnImage = Image.FromStream(ms,true);
2 голосов
/ 17 февраля 2014

Вы не объявили returnImage как переменную любого вида:)

Это должно помочь:

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;
}
2 голосов
/ 09 января 2013

Это основано на ответе Хольстебро и комментариях здесь: Получение объекта Image из байтового массива

Bitmap newBitmap;
using (MemoryStream memoryStream = new MemoryStream(byteArrayIn))
    using (Image newImage = Image.FromStream(memoryStream))
        newBitmap = new Bitmap(newImage);
return newBitmap;
0 голосов
/ 27 декабря 2017

Я нашел этого парня Конвертировать массив в изображение

        private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            string hasil = "D:\\coba1000.jpg";
            System.IO.File.WriteAllBytes(@hasil, bytestosend);


            pictureBox1.ImageLocation = @hasil;
        }
        catch { }
    }
...