前言
我们在开发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 类去复制一份图像数据即可。