从读取Excel文件引申出的问题(下)

从上一篇的:从读取Excel文件引申出的问题(上)中,对于从Excel文件中抓取的图片读取速度太慢的,问题主要来源于IComObject对象在经过了Copy和Paste后,造成了对内存及各种计算上的消耗后,速度已大大下降鸟。这几天研究来研究去,也没个结果,索性将这个问题再次提起,借众人之力。

在这一次的实验中,我借助了Marshal类的功能,提取IcomObject对象的指针,通过指针,希望读取Excel文件中图形对象的内容,代码如下:

 

代码
byte[] bytes =null;
List
<byte> bs =new List<byte>();
IntPtr intptr
= item.GetType().TypeHandle.Value;
byte b =1;
int s =0;
while (b >0) {b = Marshal.ReadByte(intptr, s * Marshal.SizeOf(typeof(IntPtr))); s++;bs.Add(b);}
bytes
= bs.ToArray();

然后 将读取到的对象内容通过流的形式写入文件。

using (FileStream fs =new FileStream(@"D:\temp\"+ row +".jpg", FileMode.Create, FileAccess.Write))
{
fs.Write(bytes,
0, bytes.Length);
fs.Flush();
fs.Close();
}

最后发现太失败了,内容是读取出来了,但是基本上只读取了10K的内容,图像是无法显示的。这是什么问题呢?

本来嘛,希望通过Marshal来获取对象大小的,最后发现无效,抛出了ArgumentException异常:

int len = Marshal.SizeOf(typeof(Excel.Shape));
类型“Microsoft.Office.Interop.Excel.Shape”不能作为非托管结构进行封送处理;无法计算有意义的大小或偏移量。

算了,还是走回老路吧,最后被逼得没办法了,来招狠的,在图像保存格式上下功夫,这次我不再把获取到的Shape强制转换为BitMap对象,因为从DataObject对象中,我们可以获取到剪贴板对象中支持转换的对象格式,如下:

这下好了,我直接从DataObject对象中获取图片对象,即Image对象,再直接保存,保存的时候会发生一点小问题,即图像格式的问题。

代码
DataObject data = (DataObject)Clipboard.GetDataObject();
Image img
= data.GetImage();
img.Save(
@"D:\temp\aa\"+ row +".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
Clipboard.Clear();
// 清除剪贴板内容

Clipboard.Clear();  //  清除剪贴板内容

通过对比,发现保存为GIF格式可获取最高压缩级,Bmp为高保真级存储,消耗的内存和时间还真不是一般的多,当然,我选择了中庸方案:Jpeg格式。下面的数据为同一幅18KB的图片在各种格式下的存储大小,即所谓的压缩比了。

Jpeg:10KB
Bmp:145KB
PNG:18KB
GIF:7KB
Tiff:29KB

到最后的完整代码实际上为六行代码。

代码
item.Copy();
DataObject data
= (DataObject)Clipboard.GetDataObject();
Image img
= data.GetImage();
img.Save(
@"D:\temp\aa\"+ row +".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
Clipboard.Clear();
img.Dispose();

但是还是那句话,效率上还是上不去,唯一可做的是,通过把图片进行有损压缩,达到一定程度的提高速度,但是这不是最终想的结果,因为Image对象在写入文件时,默认单次写入大小最大为:1KB。不知道还有什么可以提高地方。

posted @ 2010-01-11 14:40  Ron.Liang  阅读(1860)  评论(0编辑  收藏  举报