您的位置:首页 > 其它

照片处理小工具三合一设计到实现(一)

2017-11-14 17:22 190 查看
首先上目前的软件截图:

下载地址:http://download.csdn.net/download/autumoonchina/10118243



主要功能如下:

支持照片归类,文件归类,照片缩放(包括gif动画缩放),以及克隆EXIF等功能。

实际上写这个软件,也只是因为之前我的妻子跟我提到了照片归类的需求,她的照片比较多,手机导出的照片分类比较杂乱,还有空文件夹,但是如果人工整理的话比较麻烦,于是我决定自己写一个文件归类的软件,网上这类工具也挺多,但是具体到我的需求,总是各种不同,要不软件还有一些限制,总觉得还是自己写比较好,以后也可以扩充功能,于是自己写了这个软件的第一个版本。



图片分类的代码比较简单,读取EXIF信息,然后按照拍摄日期分类。

int CClassifyFiles::MovePicsByTime(const char* pStr, const char* pSavePath, const int& nProcessIndex)
{
std::string strRootDir = CStdStr::AddSlashIfNeeded(CMfcStrFile::CString2Char(g_strDir)) + "autumoon\\";

if (_access(strRootDir.c_str(), 0) != 0)
{
if (!CreateDirectory(CString(strRootDir.c_str()), NULL))
{
return -1;
}
}

std::string strPicTime;
std::string strYearMonth;

if (Get_ExifTime(pStr, strPicTime))
{
strYearMonth = strPicTime.substr(0, 7);
strYearMonth = CStdStr::RepalceAll(strYearMonth, ":");
}
else
{
CString strLastWriteTime = GetModifyTime(CString(pStr));
strYearMonth = std::string(CMfcStrFile::CString2Char(strLastWriteTime));
}

std::string strSaveDir = strRootDir + strYearMonth;

if (_access(strSaveDir.c_str(), 0) != 0)
{
if (!CreateDirectory(CString(strSaveDir.c_str()), NULL))
{
return -1;
}
}

std::string strSavePath = CStdStr::AddSlashIfNeeded(strSaveDir) + CStdStr::GetNameOfFile(pStr);

if (CStdFile::IfAccessFile(strSavePath))
{
int nNum = 0;
do
{
++nNum;
strSavePath = CStdStr::AddSlashIfNeeded(strSaveDir) + CStdStr::GetNameOfFile(pStr, false) + CStdTpl::ConvertToString(nNum) + CStdStr::GetSuffixOfFile(pStr);

} while (CStdFile::IfAccessFile(strSavePath));
}

if (strSavePath != std::string(pStr))
{
rename(pStr, strSavePath.c_str());
}

g_Mutex.Lock();
g_mLogs.insert(std::make_pair(std::string(pStr), strSavePath));
g_Mutex.Unlock();

return 0;
}


想到除了整理照片,还可以整理其他的文件,所以当时增加了整理所有文件的功能,按照“最后一次修改时间”

关键代码为:

int CClassifyFiles::MoveFilesByTime(const char* pStr, const char* pSavePath, const int& nProcessIndex)
{
std::string strDir = CMfcStrFile::CString2Char(g_strDir);

std::string strRootDir = CStdStr::AddSlashIfNeeded(strDir) + "autumoon\\";

if (_access(strRootDir.c_str(), 0) != 0)
{
if (!CreateDirectory(CString(strRootDir.c_str()), NULL))
{
return -1;
}
}

CString strLastWriteTime = GetModifyTime(CString(pStr));
std::string strYearMonth = std::string(CMfcStrFile::CString2Char(strLastWriteTime));

std::string strSaveDir = strRootDir + strYearMonth;

if (_access(strSaveDir.c_str(), 0) != 0)
{
if (!CreateDirectory(CString(strSaveDir.c_str()), NULL))
{
return -1;
}
}

std::string strSavePath = CStdStr::AddSlashIfNeeded(strSaveDir) + CStdStr::GetNameOfFile(pStr);

int nNum = 0;
if (CStdFile::IfAccessFile(strSavePath))
{
do
{
++nNum;
strSavePath = CStdStr::AddSlashIfNeeded(strSaveDir) + CStdStr::GetNameOfFile(pStr, false) + CStdTpl::ConvertToString(nNum) + CStdStr::GetSuffixOfFile(pStr);

} while (CStdFile::IfAccessFile(strSavePath));
}

if (rename(pStr, strSavePath.c_str()) < 0)
{
rename(pStr, strSavePath.c_str());
}

g_Mutex.Lock();
g_mLogs.insert(std::make_pair(std::string(pStr), strSavePath));
g_Mutex.Unlock();

return 0;
}


恢复功能是必不可少的,所以增加了log记录,可以恢复原来的文件结构,毕竟谁都有可能弄错,所以准备一碗后悔药是必要的。

关键代码:

int CClassifyFiles::RestoreFile(const char* pStr, const char* pSavePath, const int& nProcessIndex)
{
std::string strOldPath = g_mLogs[std::string(pStr)];
std::string strOldDir = CStdStr::GetDirOfFile(strOldPath);
if (_access(strOldDir.c_str(), 0) != 0)
{
CStdDir::CreateDir(strOldDir);
}

if (strOldPath != std::string(pStr))
{
rename(pStr, strOldPath.c_str());
}

return 0;
}


于是第一个版本就完成了,实现了文件的整理,这里发现一个问题就是,多线程会出问题,因为重命名文件的速度本身就很快,用多线程反而会出现资源抢占的问题,以上所以这个模块最终选择了单线程实现,但是保留了多线程的接口。

(未完待续)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息