从字节获取图像大小而不重新分配整个数据

时间:2015-10-08 19:49:27

标签: c# .net image graphics

有没有办法在不必从字节中加载整个Image对象的情况下获取图像的大小?

我现在这样做:

private Size GetImageSize(byte[] data)
{
     using(Stream dataStream = new MemoryStream(data))
     using(Image image = Image.FromStream(dataStream))
         return image.Size;
}

但正如您所看到的,我正在创建一个新的MemoryStream并复制所有图像数据,浪费空间,只是为了获得图像的大小。

1 个答案:

答案 0 :(得分:0)

我认为您的代码是正确的方法,只需使用Image.FromStream Method (Stream, Boolean, Boolean)重载就可以跳过像这样的图像数据验证

static Size GetImageSize(byte[] data)
{
     using(var dataStream = new MemoryStream(data))
     using(var image = Image.FromStream(dataStream, false, false))
         return image.Size;
}
  

但正如您所看到的,我正在创建一个新的MemoryStream并复制所有图像数据,浪费空间,只是为了获得图像的大小。

首先,使用的MemoryStream构造函数不会复制任何数据,只是创建传递的Stream的{​​{1}}包装器(视图)。

其次,虽然不能保证,但您可以依靠GDI +图像优化延迟数据处理/缓冲区分配,并略微传递[]byte

这是一个代码,可用于尝试查看正在进行的操作:

validateImageData=false

您可以在public struct ReadInfo { public long Position; public int Count; public override string ToString() { return "Pos: " + Position + " Count: " + Count; } } class TrackingMemoryStream : MemoryStream { public TrackingMemoryStream(byte[] buffer) : base(buffer) { } public int TotalReadCount; public List<ReadInfo> ReadInfo = new List<ReadInfo>(); public override int Read(byte[] buffer, int offset, int count) { var info = new ReadInfo { Position = Position }; info.Count = base.Read(buffer, offset, count); ReadInfo.Add(info); TotalReadCount += info.Count; return info.Count; } } static Size GetImageSize(byte[] data) { using (var dataStream = new TrackingMemoryStream(data)) using (var image = Image.FromStream(dataStream, false, false)) { var size = image.Size; return size; } } 行放置一个断点并检查dataStream跟踪信息。根据解码器(格式),您将看到不同的信息,但无论如何,与数据大小相比,存在非常小的块读取。当然,不能保证用于保存整个图像像素数据的内部缓冲区尚未被分配,但是很有可能被延迟。请注意,如果在调试器中展开return size;变量,您将看到非常不同的跟踪流信息,因此此时很可能已经分配了像素数据缓冲区。

总而言之,在这种情况下,我会依赖解码器来正确获取我需要的信息,而不会关心内存分配。