后来考虑到平时不管是手机还是相机,照片尺寸都比较大,保存的文件也都很大,而我们实际上并不需要那么大的文件,于是考虑可以批量修改照片尺寸,虽然市面上各种图像处理软件都能够实现该功能,但是他们很多都会导致一个问题,EXIF信息丢失!并且加入了被软件处理过的信息!这必然是我不想看到的,于是自己写了一个,采用了多线程,速度也比一般的软件快。
软件界面是这样的,改变尺寸同时保留EXIF信息。
软件基本使用正常,因为使用了GDAL库,所以对于输入图像的尺寸也没有限制,本以为这样这个小软件就结束了,结果发现一个问题,GDAL直接处理GIF文件的时候会有问题,具体表现就是如果读取GIF文件,会把彩色读取成黑白的,如果直接修改GIF的尺寸,处理之后的图片颜色信息丢失了!!
调试发现,原来读取GIF的时候,GDAL会把通道数读取成1,在网上搜索无果之后,后续考虑对GIF文件单独处理,经过抉择最终采用了CxImage类。
关键代码为:
int CResizePictures::ResizePics(const char* pInputPath, const char* pSavePath, const int& nProcessIndex)
{
CGdalUser gu;
if (!gu.Initialize(pInputPath))
{
return -1;
}
//获取exif信息
ExifPathsTags pathsTags;
ExifImageFile inImageFile;
ExifStatus status(EXIF_INVALID_FORMAT_ERROR);
ExifStatus openStatus(EXIF_INVALID_FORMAT_ERROR);
std::string dstExtension = CStdStr::ToUpperLower(CStdStr::GetSuffixOfFile(pInputPath));
bool bExif = 0 == strcmp(dstExtension.c_str(), ".jpg") || 0 == strcmp(dstExtension.c_str(), ".jpeg");
if (bExif)
{
openStatus = inImageFile.open(pInputPath, "r+");
if (openStatus != EXIF_OK) //不能用w打开照片,打开后会重新创建一张照片并将原来的照片覆盖掉
{
inImageFile.close();
}
status = inImageFile.getAllTags(0xFFE1, "Exif", pathsTags) ;
if (status != EXIF_OK)
{
inImageFile.close();
}
}
double dPropWH = (double)gu.m_nImgWidth / gu.m_nImgHeight;
int nNewWidth = g_nImgWidth;
int nNewHeight = g_nImgHeight;
double dPropScale = 1.0;
if(g_bKeepScale)
{
//如果保持比例才计算
if (gu.m_nImgWidth < gu.m_nImgHeight)
{
dPropScale = (double)nNewWidth / gu.m_nImgWidth;
nNewHeight = int(gu.m_nImgHeight * dPropScale);
if (nNewHeight <= 0)
{
nNewHeight = 1;
}
}
else
{
dPropScale = (double)nNewHeight / gu.m_nImgHeight;
nNewWidth = int(gu.m_nImgWidth * dPropScale);
if (nNewWidth <= 0)
{
nNewWidth = 1;
}
}
}
bool bGif = 0 == strcmp(dstExtension.c_str(), ".gif");
unsigned char* pData = nullptr;
if (bGif)
{
//Gif文件需要单独处理
if (CxImageUser::ResizeGif(CStdStr::s2ws(pInputPath), CStdStr::s2ws(pSavePath), nNewWidth, nNewHeight))
{
g_vLog[nProcessIndex] = (std::string(pInputPath) + "->" + std::string(pSavePath) + '\n');
}
else
{
//保存失败
g_vLog[nProcessIndex] = ("Resize" + std::string(pInputPath) + " Failed!" + '\n');
return -1;
}
}
else if (gu.readImageGDAL(&pData, nNewWidth, nNewHeight, gu.m_nBandNum, pInputPath))
{
//保存结果
if (gu.WriteImageGDAL(pSavePath, pData, nNewWidth, nNewHeight, gu.m_nBandNum))
{
if (status == EXIF_OK)
{
//增加exif信息
SetPicExifInfo(pSavePath, pathsTags);
}
g_vLog[nProcessIndex] = (std::string(pInputPath) + "->" + std::string(pSavePath) + '\n');
}
else
{
//保存失败
g_vLog[nProcessIndex] = ("Resize" + std::string(pInputPath) + " Failed!" + '\n');
return -1;
}
delete[] pData;
pData = nullptr;
}
return 0;
}
当然,这个小软件最终被合并到三合一那个软件中了。
如图:
对于GIF图像也能够实现缩放,并且保留动画效果,不过这个功能比较耗时,因为要对gif文件的每一帧都进行缩放。
于是尺寸修改功能告一段落。
(未完待续)