C#打开tif文件时内存溢出(System.OutOfMemoryException)解决办法

前言

原创性声明 此博文的出处 为http://blog.csdn.net/zhujunxxxxx/article/details/40649887如果进行转载请注明出处。本文作者原创,邮箱[email protected],如有问题请联系作者

我在做一个统计图片长和宽的软件时遇到一个问题,本来是用的

 Image img = null;
                    img = Image.FromFile(f.FullName);
                    w = img.Width;
                    h = img.Height;


这段代码来获取图片的长和宽的,本来在我的win7下面 16G内存的机器上跑的完全没问题,结果我把这个程序放在了xp系统上面运行,那么问题就来了

错误问题

程序竟然在创建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图像的变量设置
        /// 
        /// 存储读入的TIF图像的宽度
        /// 
        private int Width;
        /// 
        /// 存储读入的TIF图像的高度
        /// 
        private int Heigth;
        /// 
        /// 存储读入的TIF图像的Directory Entry Count(DE)的个数
        /// 
        private short NumOfDE;
        /// 
        /// 存储下一个Directory Entry的偏移值
        /// 
        private int NextOffsetFID;
        /// 
        /// 声明一个结构,存储图像文件头Image File Header的信息
        /// 
        struct IFH
        {
            public char[] ByteOrder;
            public short Version;
            public int OffsetToFirstFID;
        }
        /// 
        /// 声明一个结构,存储Directory Entry
        /// 
        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();



你可能感兴趣的:(c#技术类,数据结构与算法)