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

后来考虑到平时不管是手机还是相机,照片尺寸都比较大,保存的文件也都很大,而我们实际上并不需要那么大的文件,于是考虑可以批量修改照片尺寸,虽然市面上各种图像处理软件都能够实现该功能,但是他们很多都会导致一个问题,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文件的每一帧都进行缩放。

于是尺寸修改功能告一段落。

(未完待续)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
设计将要实现的是一个单机图片浏览软件,从其目标功能及特点分析,将本软件功能划分如下: 可以打开BMP、PCX、TGA、JPEG及GIF图像。 不论打开的是上述图像中的哪一种,用户均能以其中的任意一种格式将其保存。 在查看一幅图像时,可以逐渐放大、缩小;可以直接调整图像显示大小到适合屏幕或恢复为原始状态;可以直接将显示大小调整为原图像的50%、75%、150%、200%。 在查看一幅图像时,可以对其进行顺时针90º、逆时针90º、180º旋转。 在查看一幅图像时,可以直接调用Windows画图程序打开并进行编辑或以系统默认关联的程序打开查看或编辑。 软件提供“上一张”、“下一张”的功能,即在打开一幅图像后,可以不再使用“打开”命令而用鼠标单击“上一张”按钮、“下一张”按钮或按键盘上的Page Up键、Page Down键直接浏览当前图片所在文件夹中的其他图片。 可以进行全屏幕浏览,并在全屏幕浏览时提供“幻灯片播放”的功能,自动显示当前文件夹下的所有图像。同时,在全屏幕浏览时,在屏幕右上角显示一个浮动工具条,提供“停止幻灯片播放”、“上一张”、“下一张”、“逐渐放大”、“逐渐缩小”、“适合屏幕大小”、“原始大小”及“退出全屏浏览”的功能。 按F11键可以进行全屏浏览、非全屏浏览的切换,同时,在进行全屏幕浏览时按ESC键也可以退出全屏状态。 在载入图片时,提供“从上往下”、“从下往上”、“从左往右”、“从右往左”、“左上进入”、“左下进入”、“右上进入”、“右下进入”、“马赛克”、“百叶窗”等显示效果,并且可以由用户选择是否使用及使用哪个效果,用户也可以选择让系统随机选择效果。 在查看图片时,用户也可以让软件随时显示“水平百叶窗”、“垂直百叶窗”、“马赛克”、“向上扫描”、“向下扫描”等效果。 在查看图片时,可以选择从当前目录中删除该图片,并将其放入系统回收站中。 在窗口的用户区右键单击鼠标,则弹出快捷菜单,显示常用的操作命令。 在查看图片时,标题栏显示当前打开的图片的文件名;状态栏从左到右依次显示图片的全路径、当前的显示比例、图片文件的大小(KB)、图像的大小、鼠标当前的坐标。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值