2012-02-07 3 views
56

Я хочу преобразовать массив байтов в изображение.Байт-массив для преобразования изображений

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

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.

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

+0

Вы проверили, что байты изображения в вашем запросе действительны? Вы можете выполнить File.WriteAllBytes («myimage.jpg», byteArrayIn) для проверки. – Holstebroe

ответ

4

попытка (ДОПОЛНЕНО)

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

Спасибо, но не решили проблему из этого кода –

+2

Не имеет смысла писать массив байтов в поток памяти после того, как он был инициализирован с помощью того же массива байтов. На самом деле я не уверен, что MemoryStream позволяет писать за пределами длины, указанной в конструкторе. – Holstebroe

+0

@TanzeelurRahman см. Мой отредактированный ответ ... – Yahia

70

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

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

using (var ms = new MemoryStream(byteArrayIn)) 
{ 
    return Image.FromStream(ms); 
} 
+0

Вы можете также явно сделать поток памяти незаписанным после инициализации: новый MemoryStream (byteArrayIn, false) – Holstebroe

+0

Нет, этот код не решен моя проблема –

+19

Это нарушает спецификацию в MSDN для изображения ,FromStream(), где говорится: «Вы должны держать поток открытым на всю жизнь изображения». См. Также http://stackoverflow.com/questions/3290060/getting-an-image-object-from-a-byte-array – RenniePet

2

Это вдохновляется ответ Holstebroe, в плюс комментарии здесь: 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; 
55

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

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

EDIT:

Смотрите здесь для обновленной версии этого ответа: How to convert image in byte array

+0

Отличное ... сэкономленное время – PawanS

+0

AAAh спасибо, наконец, хороший ответ. Почему так много ответов с потоком памяти, это вызывает у меня столько проблем. большое спасибо ! – Julian50

+0

Хороший ответ! это можно использовать в отдельной функции, тогда как все другие предложения, использующие MemoryStream, не могут (поток должен оставаться открытым на всю жизнь изображения) –

0

Большую часть времени, когда это происходит, это плохие данные в столбце SQL. Это правильный способ вставить в столбец изображения:

INSERT INTO [TableX] (ImgColumn) VALUES (
(SELECT * FROM OPENROWSET(BULK N'C:\....\Picture 010.png', SINGLE_BLOB) as tempimg)) 

Большинство людей делают это неправильно таким образом:

INSERT INTO [TableX] (ImgColumn) VALUES ('C:\....\Picture 010.png')) 
0

Привет попробуйте ссылку ниже для меня также есть один и тот же вопрос, и я получил решен попробуйте ссылку ниже он будет помогает U enter link description here

2

Вы не объявленную 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; 
} 
+1

Код полезен как идея, но, конечно, не будет работать так, как написано. returnImage должен быть объявлен вне секции try/catch. Также returnImage должен быть создан в 'catch' - я создаю одноразрядное растровое изображение: var image = new Bitmap (1, 1); MemoryStream stream = новый MemoryStream(); image.Save (поток, ImageFormat.Jpeg); stream.Position = 0; – Reid

4

Все представленные ответы предполагают, что массив байтов содержит данные в известном представлении формата файла, например: 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; 
    } 
} 

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

+0

в качестве ссылки MSDN: Bitmap (Int32, Int32): «Этот конструктор создает битмап с значением перечисления PixelFormat Format32bppArgb.», Что означает, что байт [0] синий, байт [1] зеленый, байт [2] равен красный, байт [3] - альфа, байт [4] - синий и т. д. – brk

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

Хотя обычно это не хорошая идея, я помещаю GC.Collect() перед потоком памяти. У меня не хватало памяти, когда я предварительно загрузил большое количество больших графических файлов, как bytearrays в память, а затем превратил их в изображения во время просмотра. – Kayot

6

Хотелось бы отметить, что в решении, предоставленном @ 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

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

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

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

Связанные ответ: C# - RGB Buffer from Bitmap different from C++

-2

Я нашел эти ребята Convert array to image

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


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

есть простой подход, как показано ниже, вы можете использовать метод FromStream изображения, чтобы сделать трюк, Только не забудьте использовать системы .Рисование;

// 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; 
} 
Смежные вопросы