C#读取保存图像踩坑之FileStream类

前言

我们在开发C#上位机程序的过程中经常需要读取本地图像以及将图像数据主要是bitmap图像保存到本地,本文就来介绍读取和保存图像数据过程中遇到的奇葩大坑之一FileStream类读取图像。

1、读取图像函数如下:

csharp 复制代码
  Bitmap GetImg_Error1(string fileName)
        {
            Bitmap orig_Bitmap = null;
            try
            {
                using (FileStream fs = new FileStream(fileName, FileMode.Open))
                {
                    orig_Bitmap = new Bitmap(fs);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"加载图像异常:{ex.Message + ex.StackTrace },{fileName}");
            }
            return orig_Bitmap;
        }

我们这里读取了三种图像数据,jpg、png、bmp,分别如下;

2、读取jpg

下面的代码读取"1.jpg"图像10次,并且存入一个List中,最后执行保存图像方法。

csharp 复制代码
  private void btn_jpg_Click(object sender, EventArgs e)
        {
            string fileName = "1.jpg";
            bitmapList.Clear();
            int count = 10;
            for (int i = 0; i < count; i++)
            {
                Bitmap bmp = GetImg_Error1(fileName);
                bitmapList.Add(bmp);
            }

            for (int i = 0; i < bitmapList.Count; i++)
            {
                string fileNameNew = (i + 10) + ".bmp";
                bitmapList[i].Save(fileNameNew);
            }
        }

保存图像数据过程中会抛出异常,上面的代码看起来没啥问题,但是为啥报错了,原因是JPEG 是压缩格式,Bitmap 可能延迟解码,保存时需要重新访问流,但是这时候FileStream流已经被释放了,所以就报错了。

3、读取png

下面的代码读取"1.jpg"图像10次,并且存入一个List中,最后执行保存图像方法,下面的代码没有报错。

csharp 复制代码
 private void btn_png_Click(object sender, EventArgs e)
    {
        string fileName = "1.png";
        bitmapList.Clear();
        int count = 10;
        for (int i = 0; i < count; i++)
        {
            Bitmap bmp = GetImg_Error1(fileName);
            bitmapList.Add(bmp);
        }

        for (int i = 0; i < bitmapList.Count; i++)
        {
            string fileNameNew = (i + 10) + ".bmp";
            bitmapList[i].Save(fileNameNew);
        }
    }

4、读取bmp

下面的代码读取"1.bmp"图像10次,并且存入一个List中,最后执行保存图像方法,下面的代码没有报错。

csharp 复制代码
 private void btn_bmp_Click(object sender, EventArgs e)
    {
        string fileName = "1.bmp";
        bitmapList.Clear();
        int count = 10;
        for (int i = 0; i < count; i++)
        {
            Bitmap bmp = GetImg_Error1(fileName);
            bitmapList.Add(bmp);
        }

        for (int i = 0; i < bitmapList.Count; i++)
        {
            string fileNameNew = (i + 10) + ".bmp";
            bitmapList[i].Save(fileNameNew);
        }
    }

5、解决方法

以上读取三种图像居然得到了不同的结果,那么能不能读取三种不同图像得到相同结果呢?答案是是可以的,只需要在图像图像的时候,对图像进行复制可以,代码如下:

csharp 复制代码
    Bitmap GetImg_OK(string fileName)
        {
            Bitmap copyBmp = null;
            try
            {
                using (FileStream fs = new FileStream(fileName, FileMode.Open))
                {
                    using (Bitmap orig_Bitmap = new Bitmap(fs))
                    {
                        copyBmp = new Bitmap(orig_Bitmap.Width, orig_Bitmap.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        using (Graphics g = Graphics.FromImage(copyBmp))
                        {
                            g.DrawImage(orig_Bitmap, 0, 0, orig_Bitmap.Width, orig_Bitmap.Height);
                        }
                    };
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"加载图像异常:{ex.Message + ex.StackTrace },{fileName}");
            }
            return copyBmp;
        }

上面的代码中首先依靠FileStream获取了图像orig_Bitmap,然后使用Graphics 类去复制一份图像数据即可。

马工撰写的年入30万+C#上位机项目实战必备教程(点击下方链接即可访问文章目录)

1、《C#串口通信从入门到精通》

2、《C#与PLC通信从入门到精通 》

3、《C# Modbus通信从入门到精通》

4、《C#Socket通信从入门到精通 》

5、《C# MES通信从入门到精通》

6、《winform控件从入门到精通》

7、《C#操作MySql数据库从入门到精通》

以上教程CSDN订阅已超过2000+~

相关推荐
名字还没想好☜10 小时前
Go 的 io.Reader/Writer 组合实战:io.Copy、TeeReader、MultiWriter 优雅处理数据流
开发语言·后端·golang·go·iphone
郝学胜-神的一滴10 小时前
Qt 高级编程 042:进度条从入门到自定义美化
开发语言·c++·qt·软件开发·用户界面
鸿芯微控科技11 小时前
压电纳米定位分辨率怎么测?噪声、带宽、最小可检测位移与Python分析
开发语言·python·噪声分析·压电执行器·纳米定位·位移测量
@小匠11 小时前
Spring Boot Nacos绑定 Map 时中文 key 导致启动失败:一次从复现到源码的排查实录
java·开发语言·前端
Knight_AL11 小时前
Lombok @Builder 踩坑:build() 前后对象类型不一样
android·java·开发语言
神明不懂浪漫11 小时前
【第五章】队列
开发语言·数据结构·经验分享·笔记·算法
吃好睡好便好11 小时前
MATLAB仿真框图3
开发语言·matlab·仿真·simulink
-银雾鸢尾-12 小时前
C#中的反射关键类-Type
开发语言·c#
大黄说说12 小时前
Java 与 Kotlin 混合开发避坑指南:老项目平滑迁移 Kotlin 实操手册
java·开发语言·kotlin
breeze jiang12 小时前
JavaScript 单例模式:用静态属性保证 Popup 只创建一次
开发语言·javascript·单例模式