简体   繁体   English

字节数组到图像的转换

[英]Byte array to image conversion

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.当我到达带有注释的行时,会发生以下异常: Parameter is not valid.

How can I fix whatever is causing this exception?如何解决导致此异常的原因?

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

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.也许我遗漏了一些东西,但对我来说,这个单行代码适用于包含 JPEG 文件图像的字节数组。

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

EDIT:编辑:

See here for an updated version of this answer: How to convert image in byte array有关此答案的更新版本,请参见此处: 如何在字节数组中转换图像

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

I'd like to note there is a bug in solution provided by @isaias-b.我想指出@isaias-b 提供的解决方案中有一个错误。

That solution assume that stride is equal to row length.该解决方案假设stride等于行长。 But it is not always true.但这并不总是正确的。 Due to memory alignments performed by GDI, stride can be greater then row length.由于 GDI 执行的内存对齐,stride 可以大于行长度。 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:为了说明它会导致什么,让我们生成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);
}

If we will copy entire array as-is to address pointed by bmpData.Scan0 , we will get following image.如果我们将整个数组原样复制到bmpData.Scan0指向的地址,我们将得到以下图像。 Image shifting because part of image was written to padding bytes, that was ignored.图像移位,因为部分图像被写入填充字节,这被忽略了。 Also that is why last row is incomplete:这也是最后一行不完整的原因:

忽略步幅

But if we will copy row-by-row shifting destination pointer by bmpData.Stride value, valid imaged will be generated:但是如果我们通过bmpData.Stride值逐行复制目标指针,则会生成有效的图像:

考虑到步幅

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: C# - RGB Buffer from Bitmap different from C++相关答案: C# - 位图的 RGB 缓冲区与 C++ 不同

All presented answers assume that the byte array contains data in a known file format representation, like: gif, png or jpg.所有给出的答案都假定字节数组包含已知文件格式表示的数据,例如:gif、png 或 jpg。 But i recently had a problem trying to convert byte[] s, containing linearized BGRA information, efficiently into Image objects.但是我最近在尝试将包含线性化 BGRA 信息的byte[]有效地转换为Image对象时遇到了问题。 The following code solves it using a Bitmap object.下面的代码使用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 is a slightly variation of a solution which was posted on this site .这是发布在此站点上的解决方案的一个略微变体。

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 ;有一个简单的方法如下,你可以使用图像的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;
}

在一行中:

Image.FromStream(new MemoryStream(byteArrayIn));

try (UPDATE)尝试(更新)

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

一个班轮:

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

This is inspired by Holstebroe's answer, plus comments here: Getting an Image object from a byte array这是受 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;

You haven't declared returnImage as any kind of variable :)您还没有将 returnImage 声明为任何类型的变量:)

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

Most of the time when this happens it is bad data in the SQL column.大多数情况下,发生这种情况是 SQL 列中的错误数据。 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'))

First Install This Package:首先安装这个包:

Install-Package SixLabors.ImageSharp -Version 1.0.0-beta0007安装包 SixLabors.ImageSharp -Version 1.0.0-beta0007

[SixLabors.ImageSharp][1] [1]: https://www.nuget.org/packages/SixLabors.ImageSharp [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:对于获取 ImageFormat,请使用以下代码:

IImageFormat format = Image.DetectFormat(byteArray);

For Mutate Image Use Below Code:对于变异图像,请使用以下代码:

image.Mutate(x => x.Resize(new Size(1280, 960)));

I suggest using ImageSharp我建议使用 ImageSharp

Image<Bgra32> image = SixLabors.ImageSharp.Image.LoadPixelData<Bgra32>
                        (byteArray
                        , pageWidth
                        , pageHeight);

I found this guys 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 { }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM