为什么会 Out Of Memory?

时间:2021-03-03 23:02:31
我用 BitMap,就加载几张图片,画图而已...报 Out Of Memory异常...何解?
是不是代码的问题?

10 个解决方案

#1


换几张画图画出的图,如果还不行,那就是代码问题,如果行,是你的图片格式不标准。

#2


资源释放了吗?还是不断的加载到内存么?

#3


引用 2 楼 guwei4037 的回复:
资源释放了吗?还是不断的加载到内存么?

释放了哈...不过是我是用两个using嵌套,每个using是一个BitMap,...按理上应该一个...我再看看能不再优化代码再上贴代码...不过像版主说的,我换图片做后没事...
测试有问题的图片,是我自己用画图工具画的 .png格式...

#4


引用 1 楼 caozhy 的回复:
换几张画图画出的图,如果还不行,那就是代码问题,如果行,是你的图片格式不标准。


开始我用的是 自己用画图工具画的 .png图片,到底 8 张就有问题了...然后我换图片..
我用照相机拍的图片,做到底 40张就有问题了...我觉得可能我代码有问题...我先看下能不能优化..我待会上代码下...

#5


引用 1 楼 caozhy 的回复:
换几张画图画出的图,如果还不行,那就是代码问题,如果行,是你的图片格式不标准。

版主,在优化的过程中,碰到没有见过的报错:我上完整代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace FontWatermarkDemo {
    public partial class Form1: Form {
        #region 字体成员及其图片元素.
        //默认字体.
        private float fontSize = 8;
        private FontStyle fontStyle = FontStyle.Regular;
        private Color fontColor = Color.Black;
        //需要指定.
        private FontFamily fontFamily = null;
        private Font font = null;
        private Bitmap bMapPreview; //预览图片.
        private Bitmap bMapSave;    //保存的图片.
        #endregion
        public Form1() {
            InitializeComponent();
            //退出.
            btnExit.Click += (sender, e) => { this.Dispose(); };
        }
        //加载图片.
        private void btnLoadImg_Click(object sender, EventArgs e) {
            openFD.Filter = "图片格式|*.jpeg;*.jpg;*.png;*.bmp;*.gif";  //过滤文件.
            if(openFD.ShowDialog() != DialogResult.OK) return;
            foreach(var file in openFD.FileNames) { //将FileInfo对象加到ListBox.
                OwnFileInfo oFile = new OwnFileInfo(file);
                lboxImgList.Items.Add(oFile);
            }
        }
        //检查是否已加载图片.
        private void txtWatermarkFontInput_TextChanged(object sender, EventArgs e) {
            if(lboxImgList.Items.Count <= 0) {
                MessageBox.Show("请先加载图片", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            OwnFileInfo file = lboxImgList.Items[0] as OwnFileInfo;
            if(file != null)
                FontWatermark(txtWatermarkFontInput.Text.Trim(), file, 0);
        }
        //设置字体.
        private void btnSetFont_Click(object sender, EventArgs e) {
            fontD.ShowApply = true; //显示"应用"按钮.
            fontD.ShowHelp = false; //不显示"帮助"按钮.
            if(fontD.ShowDialog() != DialogResult.No) {  //响应"应用"或"确定"按钮.
                Font fontNew = fontD.Font;
                fontSize = fontNew.Size;
                fontStyle = fontNew.Style;
                fontFamily = fontNew.FontFamily;
                fontColor = fontD.Color;
            }
            OwnFileInfo file = lboxImgList.Items[0] as OwnFileInfo;
            if(file != null)
                FontWatermark(txtWatermarkFontInput.Text.Trim(), file, 0);
        }
        //水印文字的显示方法. 
        /// <summary>
        /// 水印文字.
        /// </summary>
        /// <param name="strInput">输入的文字.</param>
        /// <param name="imgFullPath">水印图片的完整路径.</param>
        /// <param name="tag">标识,如"0"表示预览不保存,"1"表示预览保存.</param>
        void FontWatermark(string strInput, OwnFileInfo file, int tag) {
            SolidBrush sBrush = new SolidBrush(fontColor);  //画文字的刷子.
            switch(tag) {
                case 0:
                    using(bMapPreview = new Bitmap(picBoxWatermarkPreview.Width, picBoxWatermarkPreview.Height)) {
                        FontWatermarkDealSaveOrNot(bMapPreview, sBrush, strInput, file, 0);
                        picBoxWatermarkPreview.Image = bMapPreview; //用PictureBox显示临时图片.
                    }
                    break;
                case 1:
                    using(bMapSave = new Bitmap(Image.FromFile(file.FileName))) {
                        FontWatermarkDealSaveOrNot(bMapSave, sBrush, strInput, file, 1);
                    }
                    break;
                default:
                    throw new ArgumentException("unknow tag");
            }
        }
        //水印文字的显示,处理是否保存的内部方法.
        void FontWatermarkDealSaveOrNot(Image bMap, Brush brush, string strInput, OwnFileInfo file, int tag) {
            using(Graphics g = Graphics.FromImage(bMap)) {
                SizeF sizeFont; //字体宽高.
                int fWidth;   //字体宽度.
                int fHeight;  //字体的高度.
                if(fontFamily == null) {    //未设定字体.
                    font = new Font(strInput, fontSize);
                    sizeFont = g.MeasureString(strInput, font);
                    fWidth = (int)sizeFont.Width;
                    fHeight = (int)sizeFont.Height;
                }
                else {
                    font = new Font(fontFamily, fontSize, fontStyle);
                    sizeFont = g.MeasureString(strInput, font);
                    fWidth = (int)sizeFont.Width;
                    fHeight = (int)sizeFont.Height;
                }
                //画字体的位置.
                Point fontPosition = new Point((bMap.Width - fWidth) / 2, (bMap.Height - fHeight) / 2);
                if(tag == 0)    //指定预览.
                    g.Clear(Color.LightBlue);   //画布背景色.
                g.DrawString(strInput, font, brush, fontPosition);
                if(tag == 1)    //指定保存.
                    bMapSave = new Bitmap(Image.FromFile(file.FileName));
            }
        }
        //存储要保存图片的路径.
        private void btnSavePathBrowse_Click(object sender, EventArgs e) {
            if(folderBD.ShowDialog() != DialogResult.OK) return;
            txtSavePath.Text = folderBD.SelectedPath;
        }
        //确定保存.
        private void btnConfirm_Click(object sender, EventArgs e) {
            foreach(var f in lboxImgList.Items) {
                OwnFileInfo file = f as OwnFileInfo;
                if(file != null)
                    FontWatermark(txtWatermarkFontInput.Text.Trim(), file, 1);
            }
        }
    }
}

#6


然后呢?是什么了...

#7


引用 1 楼 caozhy 的回复:
换几张画图画出的图,如果还不行,那就是代码问题,如果行,是你的图片格式不标准。


这是完整代码,
当执行到第 109 行,即
if(tag == 0)    //指定预览.
                    g.Clear(Color.LightBlue);   //画布背景色.

时,跑到 Main中说:
Application.Run(new Form1());

报错说,Parameter is invalid...什么情况...

#8


我找到原因了...是 Graphic先被释放,BitMap后被释放.
后来我改了一下,基本上就是这样...
当我做到 第 41 个的时候,就报 OutOfMemory 异常...这应该没错吧...哦?

#9


有个问题想问大家.
我用 BitMap加水印后,就加了 个个字"明日科技是".
是"华为行楷","粗体","初号".
就字体而已,我输出的 图片变大了很多,
从 
2.30 MB -> 5.86 MB
2.62 MB -> 8.37 MB
2.33 MB -> 7.38 MB
2.74 MB -> 8.86 MB
这是我列出的一部分,为什么变化那么大?不就几个字而已么?我觉得图片本身应该更大...何解?

#10


以上图片发福,应该是矢量图变位图的关系。

#1


换几张画图画出的图,如果还不行,那就是代码问题,如果行,是你的图片格式不标准。

#2


资源释放了吗?还是不断的加载到内存么?

#3


引用 2 楼 guwei4037 的回复:
资源释放了吗?还是不断的加载到内存么?

释放了哈...不过是我是用两个using嵌套,每个using是一个BitMap,...按理上应该一个...我再看看能不再优化代码再上贴代码...不过像版主说的,我换图片做后没事...
测试有问题的图片,是我自己用画图工具画的 .png格式...

#4


引用 1 楼 caozhy 的回复:
换几张画图画出的图,如果还不行,那就是代码问题,如果行,是你的图片格式不标准。


开始我用的是 自己用画图工具画的 .png图片,到底 8 张就有问题了...然后我换图片..
我用照相机拍的图片,做到底 40张就有问题了...我觉得可能我代码有问题...我先看下能不能优化..我待会上代码下...

#5


引用 1 楼 caozhy 的回复:
换几张画图画出的图,如果还不行,那就是代码问题,如果行,是你的图片格式不标准。

版主,在优化的过程中,碰到没有见过的报错:我上完整代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace FontWatermarkDemo {
    public partial class Form1: Form {
        #region 字体成员及其图片元素.
        //默认字体.
        private float fontSize = 8;
        private FontStyle fontStyle = FontStyle.Regular;
        private Color fontColor = Color.Black;
        //需要指定.
        private FontFamily fontFamily = null;
        private Font font = null;
        private Bitmap bMapPreview; //预览图片.
        private Bitmap bMapSave;    //保存的图片.
        #endregion
        public Form1() {
            InitializeComponent();
            //退出.
            btnExit.Click += (sender, e) => { this.Dispose(); };
        }
        //加载图片.
        private void btnLoadImg_Click(object sender, EventArgs e) {
            openFD.Filter = "图片格式|*.jpeg;*.jpg;*.png;*.bmp;*.gif";  //过滤文件.
            if(openFD.ShowDialog() != DialogResult.OK) return;
            foreach(var file in openFD.FileNames) { //将FileInfo对象加到ListBox.
                OwnFileInfo oFile = new OwnFileInfo(file);
                lboxImgList.Items.Add(oFile);
            }
        }
        //检查是否已加载图片.
        private void txtWatermarkFontInput_TextChanged(object sender, EventArgs e) {
            if(lboxImgList.Items.Count <= 0) {
                MessageBox.Show("请先加载图片", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            OwnFileInfo file = lboxImgList.Items[0] as OwnFileInfo;
            if(file != null)
                FontWatermark(txtWatermarkFontInput.Text.Trim(), file, 0);
        }
        //设置字体.
        private void btnSetFont_Click(object sender, EventArgs e) {
            fontD.ShowApply = true; //显示"应用"按钮.
            fontD.ShowHelp = false; //不显示"帮助"按钮.
            if(fontD.ShowDialog() != DialogResult.No) {  //响应"应用"或"确定"按钮.
                Font fontNew = fontD.Font;
                fontSize = fontNew.Size;
                fontStyle = fontNew.Style;
                fontFamily = fontNew.FontFamily;
                fontColor = fontD.Color;
            }
            OwnFileInfo file = lboxImgList.Items[0] as OwnFileInfo;
            if(file != null)
                FontWatermark(txtWatermarkFontInput.Text.Trim(), file, 0);
        }
        //水印文字的显示方法. 
        /// <summary>
        /// 水印文字.
        /// </summary>
        /// <param name="strInput">输入的文字.</param>
        /// <param name="imgFullPath">水印图片的完整路径.</param>
        /// <param name="tag">标识,如"0"表示预览不保存,"1"表示预览保存.</param>
        void FontWatermark(string strInput, OwnFileInfo file, int tag) {
            SolidBrush sBrush = new SolidBrush(fontColor);  //画文字的刷子.
            switch(tag) {
                case 0:
                    using(bMapPreview = new Bitmap(picBoxWatermarkPreview.Width, picBoxWatermarkPreview.Height)) {
                        FontWatermarkDealSaveOrNot(bMapPreview, sBrush, strInput, file, 0);
                        picBoxWatermarkPreview.Image = bMapPreview; //用PictureBox显示临时图片.
                    }
                    break;
                case 1:
                    using(bMapSave = new Bitmap(Image.FromFile(file.FileName))) {
                        FontWatermarkDealSaveOrNot(bMapSave, sBrush, strInput, file, 1);
                    }
                    break;
                default:
                    throw new ArgumentException("unknow tag");
            }
        }
        //水印文字的显示,处理是否保存的内部方法.
        void FontWatermarkDealSaveOrNot(Image bMap, Brush brush, string strInput, OwnFileInfo file, int tag) {
            using(Graphics g = Graphics.FromImage(bMap)) {
                SizeF sizeFont; //字体宽高.
                int fWidth;   //字体宽度.
                int fHeight;  //字体的高度.
                if(fontFamily == null) {    //未设定字体.
                    font = new Font(strInput, fontSize);
                    sizeFont = g.MeasureString(strInput, font);
                    fWidth = (int)sizeFont.Width;
                    fHeight = (int)sizeFont.Height;
                }
                else {
                    font = new Font(fontFamily, fontSize, fontStyle);
                    sizeFont = g.MeasureString(strInput, font);
                    fWidth = (int)sizeFont.Width;
                    fHeight = (int)sizeFont.Height;
                }
                //画字体的位置.
                Point fontPosition = new Point((bMap.Width - fWidth) / 2, (bMap.Height - fHeight) / 2);
                if(tag == 0)    //指定预览.
                    g.Clear(Color.LightBlue);   //画布背景色.
                g.DrawString(strInput, font, brush, fontPosition);
                if(tag == 1)    //指定保存.
                    bMapSave = new Bitmap(Image.FromFile(file.FileName));
            }
        }
        //存储要保存图片的路径.
        private void btnSavePathBrowse_Click(object sender, EventArgs e) {
            if(folderBD.ShowDialog() != DialogResult.OK) return;
            txtSavePath.Text = folderBD.SelectedPath;
        }
        //确定保存.
        private void btnConfirm_Click(object sender, EventArgs e) {
            foreach(var f in lboxImgList.Items) {
                OwnFileInfo file = f as OwnFileInfo;
                if(file != null)
                    FontWatermark(txtWatermarkFontInput.Text.Trim(), file, 1);
            }
        }
    }
}

#6


然后呢?是什么了...

#7


引用 1 楼 caozhy 的回复:
换几张画图画出的图,如果还不行,那就是代码问题,如果行,是你的图片格式不标准。


这是完整代码,
当执行到第 109 行,即
if(tag == 0)    //指定预览.
                    g.Clear(Color.LightBlue);   //画布背景色.

时,跑到 Main中说:
Application.Run(new Form1());

报错说,Parameter is invalid...什么情况...

#8


我找到原因了...是 Graphic先被释放,BitMap后被释放.
后来我改了一下,基本上就是这样...
当我做到 第 41 个的时候,就报 OutOfMemory 异常...这应该没错吧...哦?

#9


有个问题想问大家.
我用 BitMap加水印后,就加了 个个字"明日科技是".
是"华为行楷","粗体","初号".
就字体而已,我输出的 图片变大了很多,
从 
2.30 MB -> 5.86 MB
2.62 MB -> 8.37 MB
2.33 MB -> 7.38 MB
2.74 MB -> 8.86 MB
这是我列出的一部分,为什么变化那么大?不就几个字而已么?我觉得图片本身应该更大...何解?

#10


以上图片发福,应该是矢量图变位图的关系。