从字节数组中获取图像对象

17

我有一个存储在数据库中的图像的字节数组。我想创建一个Image对象,创建几个不同尺寸的图像,并将它们存储回数据库(保存回一个字节数组)。

我不担心数据库部分或调整大小的部分。但是是否有一种简单的方法可以加载Image对象而不必将文件保存到文件系统,然后在完成调整大小后将其放回字节数组中?如果可以,我希望全部在内存中完成。

Something like:
Image myImage = new Image(byte[]);
or
myImage.Load(byte[]);
4个回答

30
你可以使用MemoryStream来实现这个功能:
byte[] bytes;
...
using (var ms = new System.IO.MemoryStream(bytes)) {
   using(var img = Image.FromStream(ms)) {
      ...
   }
}

这将非常有效。你知道如何将它转换回字节数组吗?调整大小后,我需要将调整大小的图像放回数据库中。 - Dan Williams
我明白了 :) 谢谢 Image.Save(Stream, ImageFormat) - http://msdn.microsoft.com/en-us/library/ms142147.aspx - Dan Williams
10
这个答案并不完全正确,你正在从流中读取图像,然后关闭这个流。根据MSDN的说法,必须在整个Image的生命周期内保持流处于打开状态。而对于某些图像格式(并非所有),你肯定需要这样做。因此,正确的方法是从已加载的图像创建新的位图,然后释放流和原始图像的两个对象。 - arbiter
1
@arbiter:编辑以将“img”放入using(){}块中。我暂时忘记了它是IDisposable。(虽然如果你不这样做,它可能仍然可以正常工作...)谢谢! - Dave Markle

3
根据您对另一个答案的评论,您可以尝试使用以下方法对存储在byte[]中的图像执行转换,然后将结果作为另一个byte[]返回。
public byte[] TransformImage(byte[] imageData)
{
    using(var input = new MemoryStream(imageData))
    {
        using(Image img = Image.FromStream(input))
        {
            // perform your transformations

            using(var output = new MemoryStream())
            {
                img.Save(output, ImageFormat.Bmp);

                return output.ToArray();
            }
        }
    }
}

这将使您能够传递存储在数据库中的byte[],执行所需的任何转换,然后返回一个新的byte[],可以重新存储回数据库。

3

只回答问题的前半部分:这是一个一行代码的解决方案,对于包含JPEG文件图像的字节数组,我使用它效果很好。

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

编辑: 以下是稍微高级一点的解决方案:https://dev59.com/Mm865IYBdhLWcg3wduaH#16576471


0

我觉得把这个作为答案加进来会更加显眼。

并将它保存回一个字节数组中:

    public Image localImage;
    public byte[] ImageBytes;

    public FUU_Image(byte[] bytes)
    {
        using (MemoryStream ImageStream = new System.IO.MemoryStream(bytes))
        {
            localImage = Image.FromStream(ImageStream);
        }

        localImage = ResizeImage(localImage);

        using (MemoryStream ImageStreamOut = new MemoryStream())
        {
            localImage.Save(ImageStreamOut, ImageFormat.Jpeg);
            ImageBytes = ImageStreamOut.ToArray();
        }

    }

重现仲裁者的评论:ResizeImage应该在ImageStream using块内部,因为对localImage的调用可能需要在其被处理之前访问ImageStream,并且您还应该处理由ResizeImage返回的(可能是新的?)localImage。 - Douglas

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