如何将图像转换为字节数组

185

有人能否建议我如何将图像转换为字节数组,反之亦然?

我正在开发一个 WPF 应用程序,并使用流读取器。


这里的答案展示了如何转换System.Drawing.Image,但它不是WPF。 - Clemens
12个回答

243

13
您可以使用imageIn.RawFormat代替System.Drawing.Imaging.ImageFormat.Gif。请注意确保翻译后的意思与原文一致,同时简化语言以提高易读性。 - S.Serpooshan
1
这似乎并不可重复,或者至少在转换几次后,奇怪的GDI+错误开始发生。下面找到的“ImageConverter”解决方案似乎可以避免这些错误。 - Dave Cousineau
现在使用png可能会更好。 - Nyerguds
附带一提:这可能包含您不想要的其他元数据;-)为了摆脱元数据,您可能需要创建一个新的位图,并将图像传递给它,例如(new Bitmap(imageIn)).Save(ms, imageIn.RawFormat); - Markus Safar
请注意,对于MemoryStream,使用using是不必要的。您可以像数组一样返回和使用MemoryStream。 - Hoddmimes

74

要将一个图像对象转换为byte[],你可以按照以下步骤进行:

public static byte[] converterDemo(Image x)
{
    ImageConverter _imageConverter = new ImageConverter();
    byte[] xByte = (byte[])_imageConverter.ConvertTo(x, typeof(byte[]));
    return xByte;
}

5
完美回答!不需要定义“图像文件扩展名”,正是我要找的。 - Bravo
2
附带说明:这可能包含您不想要的其他元数据;-)为了摆脱元数据,您可能需要创建一个“新位图”,并像.ConvertTo(new Bitmap(x), typeof(byte[]));一样将“Image”传递给它。 - Markus Safar
1
对我来说,Visual Studio无法识别类型ImageConverter。需要使用导入语句吗? - SendETHToThisAddress
@technoman23 ImageConverterSystem.Drawing 命名空间的一部分。 - AR5HAM
3
那么,实际上它将图像转换成了什么?这些字节里面有什么? - Nyerguds
显示剩余4条评论

45

获取图像路径的字节数组的另一种方法是:

byte[] imgdata = System.IO.File.ReadAllBytes(HttpContext.Current.Server.MapPath(path));

5
他们的问题标记为WPF(因此没有理由认为它在服务器上并包含MapPath),并且显示他们已经拥有该图像(没有理由从磁盘读取图像,甚至不应假设它在磁盘上)。很抱歉,但是您的回复似乎与问题完全无关。 - Ronan Thibaudau

28

这是我目前在使用的内容。我尝试过的其他一些技术并不理想,因为它们改变了像素的位深度(24位与32位),或者忽略了图像的分辨率(dpi)。

  // ImageConverter object used to convert byte arrays containing JPEG or PNG file images into 
  //  Bitmap objects. This is static and only gets instantiated once.
  private static readonly ImageConverter _imageConverter = new ImageConverter();

将图像转换为字节数组:

  /// <summary>
  /// Method to "convert" an Image object into a byte array, formatted in PNG file format, which 
  /// provides lossless compression. This can be used together with the GetImageFromByteArray() 
  /// method to provide a kind of serialization / deserialization. 
  /// </summary>
  /// <param name="theImage">Image object, must be convertable to PNG format</param>
  /// <returns>byte array image of a PNG file containing the image</returns>
  public static byte[] CopyImageToByteArray(Image theImage)
  {
     using (MemoryStream memoryStream = new MemoryStream())
     {
        theImage.Save(memoryStream, ImageFormat.Png);
        return memoryStream.ToArray();
     }
  }

字节数组转换为图片:

  /// <summary>
  /// Method that uses the ImageConverter object in .Net Framework to convert a byte array, 
  /// presumably containing a JPEG or PNG file image, into a Bitmap object, which can also be 
  /// used as an Image object.
  /// </summary>
  /// <param name="byteArray">byte array containing JPEG or PNG file image or similar</param>
  /// <returns>Bitmap object if it works, else exception is thrown</returns>
  public static Bitmap GetImageFromByteArray(byte[] byteArray)
  {
     Bitmap bm = (Bitmap)_imageConverter.ConvertFrom(byteArray);

     if (bm != null && (bm.HorizontalResolution != (int)bm.HorizontalResolution ||
                        bm.VerticalResolution != (int)bm.VerticalResolution))
     {
        // Correct a strange glitch that has been observed in the test program when converting 
        //  from a PNG file image created by CopyImageToByteArray() - the dpi value "drifts" 
        //  slightly away from the nominal integer value
        bm.SetResolution((int)(bm.HorizontalResolution + 0.5f), 
                         (int)(bm.VerticalResolution + 0.5f));
     }

     return bm;
  }

编辑:要从jpg或png文件获取图像,您应该使用File.ReadAllBytes()将文件读入字节数组中:

 Bitmap newBitmap = GetImageFromByteArray(File.ReadAllBytes(fileName));

这样可以避免与Bitmap相关的问题,因为Bitmap希望其源流保持打开状态,而一些建议的解决方法会导致源文件被锁定。


在测试期间,我会使用以下代码将生成的位图转换回字节数组:ImageConverter _imageConverter = new ImageConverter(); lock(SourceImage) { return (byte[])_imageConverter.ConvertTo(SourceImage, typeof(byte[])); } 但是,有时会出现两种不同大小的数组。通常在大约100次迭代后会发生这种情况。但是,当我使用 new Bitmap(SourceFileName); 获取位图,然后运行该代码时,它可以正常工作。 - Moon
@Don:真的没有什么好主意。是哪些图像不会产生与输入相同的输出一致吗?当输出与预期不同的时候,您是否尝试检查输出以了解其差异原因?还是可能并不重要,可以接受“事情发生了”的事实。 - RenniePet
1
它一直在发生。虽然从未找到原因,但我有一种感觉它可能与内存分配中的4K字节边界有关。但这很容易出错。我改用带有BinaryFormatter的MemoryStream,经过250多个不同格式和大小的测试图像的测试,并循环1000次进行验证后,我能够变得非常一致。谢谢您的回复。 - Moon

21

试试这个:

public byte[] imageToByteArray(System.Drawing.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;
}

imageToByteArray(System.Drawing.Image imageIn)中的imageIn是图像路径或其他任何我们可以传递图像的方式。 - Shashank
每次我需要将图像转换为字节数组或反向转换时,我都会使用以下方法。 - Alex Essilfie
你忘记关闭MemoryStream了...顺便说一下,这段代码是从这里复制的:链接 - Qwerty01
1
@Qwerty01 调用Dispose不会更快地清理MemoryStream使用的内存,至少在当前实现中是这样。事实上,如果你关闭它,之后就无法再使用Image了,会出现GDI错误。 - Saeb Amini

15

您可以使用File.ReadAllBytes()方法将任何文件读入字节数组中。要将字节数组写入文件中,只需使用File.WriteAllBytes()方法即可。

希望这能帮到您。

您可以在这里找到更多信息和示例代码。


只是一点小提示:这可能包含您不想要的附加元数据;-) - Markus Safar
3
也许吧。我在10年前写下了这个答案,那时我还是一个新手/菜鸟。 - Shekhar

8

如果您没有引用“imageBytes”来传输流中的字节,该方法将不会返回任何内容。请确保引用“imageBytes = m.ToArray();”。

    public static byte[] SerializeImage() {
        MemoryStream m;
        string PicPath = pathToImage";

        byte[] imageBytes;
        using (Image image = Image.FromFile(PicPath)) {
            
            using ( m = new MemoryStream()) {

                image.Save(m, image.RawFormat);
                imageBytes = new byte[m.Length];
               //Very Important    
               imageBytes = m.ToArray();
                
            }//end using
        }//end using

        return imageBytes;
    }//SerializeImage

6
你只需要像素还是整个图像(包括头部)作为字节数组?
对于像素:使用Bitmap上的CopyPixels方法。类似这样:
var bitmap = new BitmapImage(uri);

//Pixel array
byte[] pixels = new byte[width * height * 4]; //account for stride if necessary and whether the image is 32 bit, 16 bit etc.

bitmap.CopyPixels(..size, pixels, fullStride, 0); 

3

代码:

using System.IO;

byte[] img = File.ReadAllBytes(openFileDialog1.FileName);

1
只有在读取文件时才能工作(即使这样,他也只能获得格式化/压缩的字节,除非它是BMP格式的)。 - BradleyDotNET

1

这是将任何类型的图像(例如PNG、JPG、JPEG)转换为字节数组的代码

   public static byte[] imageConversion(string imageName){            


        //Initialize a file stream to read the image file
        FileStream fs = new FileStream(imageName, FileMode.Open, FileAccess.Read);

        //Initialize a byte array with size of stream
        byte[] imgByteArr = new byte[fs.Length];

        //Read data from the file stream and put into the byte array
        fs.Read(imgByteArr, 0, Convert.ToInt32(fs.Length));

        //Close a file stream
        fs.Close();

        return imageByteArr
    }

1
只是一点小提示:这可能包含您不想要的附加元数据;-) - Markus Safar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接