前些日子组长让我做一个检索图片信息的程序,包括图片存储路径、图片大小、修改日期和图片长宽等信息。刚开始我以为很简单,只要做一个遍历特定文件夹下的文件,判断是否为图片文件,如果是的话就将图片的这些信息存入数据库中。用C#做起了很简单吧,只要如下代码就行了
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace DirectoryMonitor
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
DoWork();
}
public void DoWork()
{
List<string> fileList = new List<string>();
fileList = GetDirectoryFiles("D:\\TUPIAN", fileList);
CheckNewFiles(fileList);
}
/// <summary>
/// 检查所有新增的文件
/// </summary>
/// <param name="list">文件列表</param>
public void CheckNewFiles(List<string> list)
{
foreach (string strpath in list)
{
FileInfo file=new FileInfo(strpath);
long lenth=file.Length;
string size=lenth/(1024*1024)+"MB";
DateTime updatetime=file.CreationTime;
Bitmap bit=new Bitmap(strpath);
string height=bit.Size.Height.ToString();
string width=bit.Size.Width.ToString();
string path=strpath;
}
}
/// <summary>
/// 检测文件是否完整(是否复制过程)
/// 以只读的方式打开
/// 打开后直接调用文件指针到文件末端
/// </summary>
/// <param name="filename">检测的文件全路径</param>
/// <returns>返回true表示不占用,false相反</returns>
private bool CheckFileIsCompleteUploaded(string filename)
{
bool flag = true;
FileInfo info = new FileInfo(filename);
try
{
FileStream stream = info.OpenRead();
stream.Seek(info.Length, SeekOrigin.End);
stream.Dispose();
stream.Close();
}
catch (IOException ioex)
{
flag = false;
}
return flag;
}
/// <summary>
/// 递归获取文件夹下包含子文件夹的所有文件
/// </summary>
/// <param name="path">文件夹路径</param>
/// <param name="list">获取目录下的文件信息集合</param>
/// <param name="fullPath">是否获取全路径(选择否只获取文件名称)</param>
/// <returns>参数list</returns>
private List<string> GetDirectoryFiles(string path, List<string> list)
{
string[] fileNames = Directory.GetFiles(path);
string[] directories = Directory.GetDirectories(path);
foreach (string file in fileNames)
{
string a=file.Substring(file.LastIndexOf('.'),file.Length-file.LastIndexOf('.'));
if (a == ".jpeg" || a == ".png")
list.Add(file);
}
if (directories.Length > 0)
{
foreach (string dir in directories)
{
list = GetDirectoryFiles(dir, list);
}
}
return list;
}
#region 测试代码(函数)
/// <summary>
///
/// </summary>
/// <param name="list"></param>
/// <returns></returns>
private string getStringFromList(List<string> list)
{
string result = "";
foreach (string str in list)
{
result = result + str + ",\n";
}
return result;
}
#endregion
}
}
但是我做的时候却报错了,因为我所检索的图片时几百兆以上的超大图片,实例化Bitmap的时候出现内存溢出的现象。于是我开始寻找解决的方法。网上也有人遇到类似问题,但找不到解决的方法,很是惆怅。后来我只好从图片的结构入手了,网上看了看图片的结构发现在图片的物理结构的特定位置就是图片的像素信息。这样问题就解决了,不用假装bitmap,直接把像素信息提取出来就行了。下面是几种图片的像素提取方法,使用任何大小的图片:
jpeg图片:
for (int i = 0; i < fstream.Length; i++)
{
if (bts[i] == 0xFF && bts[i + 1] == 0xC0)
{
h1 = Convert.ToString((bts[i + 5] * 256) + bts[i + 6]);
w1 = Convert.ToString((bts[i + 7] * 256) + bts[i + 8]);
break;
}
}
bmp图片:
w1 = Convert.ToString((bts[21] * 256*256*256) +(bts[20] * 256*256)+(bts[19] * 256)+bts[18]);
h1 = Convert.ToString((bts[25] * 256 * 256 * 256) + (bts[24] * 256 * 256) + (bts[23] * 256) + bts[22]);
png图片:
w1 = Convert.ToString((bts[16] * 256 * 256 * 256) + (bts[17] * 256 * 256) + (bts[18] * 256) + bts[19]);
h1 = Convert.ToString((bts[20] * 256 * 256 * 256) + (bts[21] * 256 * 256) + (bts[22] * 256) + bts[23]);
bts是图片的比特率数组,w1为图片宽度,h1为图片高度。