前言
原创性声明 此博文的出处 为http://blog.csdn.net/zhujunxxxxx/article/details/40649887如果进行转载请注明出处。本文作者原创,邮箱zhujunxxxxx@163.com,如有问题请联系作者
我在做一个统计图片长和宽的软件时遇到一个问题,本来是用的
Image img = null;
img = Image.FromFile(f.FullName);
w = img.Width;
h = img.Height;
错误问题
程序竟然在创建Image类型时出现内存溢出(System.OutOfMemoryException)
错误代码: System.Drawing.Image myimg=System.Drawing.Image.FromFile(file.FullName);
当打开的文件不是图像文件时会引发的异常:
或者出现 Bitmap System.ArgumentException: 参数无效问题
这其实不是程序的问题,而是系统中内存的问题,或者图片太大了,大于65535像素了。
我测试 2G内存 BitMap最大 5000*5000,反正这个BitMap大小和机器配置有关。
win7 64位 16G内存最大 23200*23200
由于 GDI+ 解码器的限制,如果使用单维大小大于 65,535 像素的 .png 图像文件构造位图,将引发 System.ArgumentException。
获取TIF图片的长和宽
那么我们既然不能通过方面的代码加载Image对象,那么我们就没法获取图片的长度和宽度,我们有没有什么方法可以获取长度呢?
答案是肯定的,我们可以通过读取TIF的文件格式的内容获取它的长度和宽度
TIF和其它格式都是一样的文件的开头都有一段描述文件的信息
我们的方法就是获取文件中所包含长度的那段内容把它读取出来
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.IO;
namespace ImageSize
{
public class ReadTIF:IDisposable
{
#region 读入TIF图像的变量设置
/// <summary>
/// 存储读入的TIF图像的宽度
/// </summary>
private int Width;
/// <summary>
/// 存储读入的TIF图像的高度
/// </summary>
private int Heigth;
/// <summary>
/// 存储读入的TIF图像的Directory Entry Count(DE)的个数
/// </summary>
private short NumOfDE;
/// <summary>
/// 存储下一个Directory Entry的偏移值
/// </summary>
private int NextOffsetFID;
/// <summary>
/// 声明一个结构,存储图像文件头Image File Header的信息
/// </summary>
struct IFH
{
public char[] ByteOrder;
public short Version;
public int OffsetToFirstFID;
}
/// <summary>
/// 声明一个结构,存储Directory Entry
/// </summary>
struct DE
{
public short tag;
public short type;
public int length;
public int valueOffset;
}
#endregion
/*
* 实例化一个IFH结构的对象
*/
private IFH myIFH;
/*
* 初始化IFH图像文件头
*/
public void DefineIFH()
{
myIFH.ByteOrder = new char[2];
myIFH.ByteOrder[0] = Convert.ToChar(0);
myIFH.ByteOrder[1] = Convert.ToChar(0);
myIFH.Version = 0;
myIFH.OffsetToFirstFID = 0;
}
public void TifFile(string file)
{
FileStream stream = new FileStream(file, FileMode.Open, FileAccess.Read);
BinaryReader TIFReader = new BinaryReader(stream);
DefineIFH();//调用初始化IFH图像文件头
/*
* 读取图像文件头内容
*/
myIFH.ByteOrder[0] = TIFReader.ReadChar();//1个字节
myIFH.ByteOrder[1] = TIFReader.ReadChar();//1个字节
myIFH.Version = TIFReader.ReadInt16();//2个字节
myIFH.OffsetToFirstFID = TIFReader.ReadInt32();//4个字节
stream.Seek(0, SeekOrigin.Begin);//将文件的指针移到开始位置
stream.Seek(myIFH.OffsetToFirstFID, SeekOrigin.Begin);//将文件的指针移动到第一个IFD的位置处
NumOfDE = TIFReader.ReadInt16();//获取本IFD结构中目录入口DE的个数,2个字节
/*
* 获取各个目录项DE的信息
*/
DE[] myDE = new DE[NumOfDE];
for (int i = 0; i < NumOfDE; i++)
{
myDE[i].tag = TIFReader.ReadInt16();//2个字节
myDE[i].type = TIFReader.ReadInt16();//2个字节
myDE[i].length = TIFReader.ReadInt32();//4个字节
myDE[i].valueOffset = TIFReader.ReadInt32();//4个字节
}
/*
* 读取下一个Directory Entry的偏移值
*/
NextOffsetFID = TIFReader.ReadInt32();
/*
* 读取图像的宽度、高度
*/
for (int i = 0; i < NumOfDE; i++)
{
if (myDE[i].tag == 256)//图像的宽
{
Width = myDE[i].valueOffset;
}
if (myDE[i].tag == 257)//图像的高
{
Heigth = myDE[i].valueOffset;
}
}
TIFReader.Close();
stream.Close();
}
//返回宽度
public int GetW()
{
return Width;
}
//返回高度
public int GetH()
{
return Heigth;
}
public void Dispose()
{
}
}
}
使用方法
ReadTIF rt = new ReadTIF();
rt.TifFile(f.FullName);
w = rt.GetW();
h = rt.GetH();