2012-02-07 120 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; 
}