2012-02-07 157 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 2012-02-07 09:59:22

回答

4

嘗試(UPDATE)

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

感謝但尚未解決的問題 – 2012-02-07 09:51:37

+2

使用相同的字節數組初始化字節數組之後,將字節數組寫入內存流是沒有意義的。實際上我不確定MemoryStream允許超出構造函數中指定的長度寫入數據。 – Holstebroe 2012-02-07 09:53:22

+0

@TanzeelurRahman看到我編輯的答案... – Yahia 2012-02-07 10:07:54

70

你寫你的記憶流了兩次,你也沒有處置使用後的流。 您還要求圖像解碼器應用嵌入式色彩校正。

試試這個:

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

你也可以在初始化後明確地使內存流不可寫:new MemoryStream(byteArrayIn,false) – Holstebroe 2012-02-07 09:54:34

+0

沒有這個代碼沒有解決我的問題 – 2012-02-07 10:00:44

+19

這違反了MSDN中Image 。FromStream()表示「您必須保持流在圖像的整個生命週期內都處於打開狀態」。另請參見http://stackoverflow.com/questions/3290060/getting-an-image-object-from-a-byte-array – RenniePet 2013-01-09 10:21:35

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

編輯:

在這裏看到這個答案的更新版本:How to convert image in byte array

+0

偉大的...保存時間 – PawanS 2013-08-09 08:44:34

+0

AAAh謝謝,最後一個很好的答案。爲什麼如此多的答案與記憶流,這給我帶來了很多問題。非常感謝 ! – Julian50 2015-06-30 11:35:59

+0

很好的答案!這可以在一個單獨的函數中使用,而使用MemoryStream的所有其他提議都不能(Stream必須在Image的生命週期中保持打開狀態) – 2016-08-18 15:07:54

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

嗨嘗試下面的鏈接,我也得到了同樣的問題,我得到了解決試試下面的鏈接它會幫助ü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 = new MemoryStream(); image.Save(stream,ImageFormat.Jpeg); stream.Position = 0; – Reid 2017-06-11 19:33:54

4

所有提供的答案都假設字節數組包含已知文件格式表示形式的數據,如:gif,png或jpg。但是我最近遇到了一個問題,試圖將包含線性BGRA信息的byte[]有效地轉換爲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):「此構造函數創建一個Bitmap,其格式32bppArgb的PixelFormat枚舉值」,這意味着字節[0]是藍色,字節[1]是綠色,字節[2]是紅色,字節[3]是阿爾法,字節[4]是藍色,依此類推。 – brk 2018-01-13 17:25:54

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

儘管通常不是一個好主意,但我在內存流之前放了一個GC.Collect()。當我將大量大型圖形文件作爲字節碼預加載到內存中,然後在查看過程中將它們轉換爲圖像時,內存不足。 – Kayot 2017-11-06 01:59:50

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

步幅也可以是負數:

如果步幅是正數,則位圖是自上而下的。如果步幅是負數,則位圖是自下而上的。

但我沒有與這些圖像合作,這是超出我的筆記。

相關答案: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; 
}