C++生成GIF小结

 声明:所有权利保留。

转载必须说明出处:http://blog.csdn.net/cartzhang/article/details/44020175


近来需要把BMPKinect的内存图片多张合成为小GIF图片。找了找,东西不少,做个小结,以备以后用到。

一、GIF.h

此方法很简单,就是一个头文件。但是我没有尝试成功。可能的原因是我的BMP图片的生成字节顺序与GIF.H头文件所要求的不一致。

Gif.h头文件代码如下:

使用方法如下:

//GifWriter m_gif_writer;
//char* file_name = "E:\aaa.gif";
//int width = 128;
//int height = 128;
//int delay = 10;
//GifBegin(&m_gif_writer, file_name, width, height, delay);
// 代码里面自动从第一帧开始。只第一帧添加GIF的头信息
//for ()
//{
////GifWriteFrame()
//}
//GifEnd()


头文件出处出处:作者:Charlie Tangora    

github 地址:https://github.com/ginsweater/gif-h


二、CXimage 

此库开源,可随便下载。

使用下载的版本为702full版本。Vs2013编译很顺利,因为需要使用的64位版本,所以使用了x64release模式。有个与mfc相关的编译不过,直接无视了,本人用不上mfc

生成的为lib的静态库。

我把所需要的头文件和静态库拷贝的到自己建立的目录下和各个对应的文件夹下,如图:

 


Include 文件从CXimage中拷贝头文件,lib库文件为编译后生成的x64文件里面的,包括Debug版本和Release版本。

网上找了个代码,对CXimageGIF写了两个函数。本人在基础上稍微添加和修改了代码。

其实主要是处理相关文件夹方便来调用的。非常感谢网友提供,头文件和CPP文件如下:(文件出处为:http://blog.csdn.net/fengbingchun/article/details/43538081

若有问题,请随时联系,非常感谢!

mGif.h头文件:

#pragma once
#ifndef _MGIF_H__
#define _MGIF_H__

#include <string>

using namespace std;


void decoding_gif(string strGifName, string strSavePath);
void encoding_gif(string strImgPath, string strGifName);


#endif //

mGif.CPP文件:

//Cartzhang
#include "mGif.h"

#include "stdafx.h"
#include "mGif.h"
#include <iostream>
#include "ximagif.h"
#include <io.h>

using namespace std;

std::wstring s2ws(const std::string& s)
{
	int len;
	int slength = (int)s.length() + 1;
	len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
	wchar_t* buf = new wchar_t[len];
	MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
	std::wstring r(buf);
	delete[] buf;
	return r;
}

void decoding_gif(string strGifName, string strSavePath)
{
	CxImage img;

	std::wstring stemp = s2ws(strGifName); // Temporary buffer is required
	LPCWSTR PicName = stemp.c_str();
	img.Load(PicName, CXIMAGE_FORMAT_GIF);

	int iNumFrames = img.GetNumFrames();
	cout << "frames num = " << iNumFrames << endl;

	CxImage* newImage = new CxImage();

	for (int i = 0; i < iNumFrames; i++) {
		newImage->SetFrame(i);
		newImage->Load(PicName, CXIMAGE_FORMAT_GIF);

		char tmp[64];
		sprintf(tmp, "%d", i);

		string tmp1;
		tmp1 = tmp1.insert(0, tmp);

		tmp1 = strSavePath + tmp1 + ".png";
		stemp = s2ws(tmp1); // Temporary buffer is required
		PicName = stemp.c_str();
		newImage->Save(PicName, CXIMAGE_FORMAT_PNG);
	}

	if (newImage) delete newImage;
}

int TraverseFolder(const string strFilePath, string strImageNameSets[])
{
	int iImageCount = 0;

	_finddata_t fileInfo;

	long handle = _findfirst(strFilePath.c_str(), &fileInfo);

	if (handle == -1L) {
		cerr << "failed to transfer files" << endl;
		return -1;
	}

	do {
		//cout << fileInfo.name <<endl;
		strImageNameSets[iImageCount] = (string)fileInfo.name;

		iImageCount++;

	} while (_findnext(handle, &fileInfo) == 0);

	return iImageCount;
}

void encoding_gif(string strImgPath, string strGifName)
{
	string strImgSets[100] = {};

	int iImgCount = TraverseFolder(strImgPath, strImgSets);

	string strTmp = strImgPath.substr(0, strImgPath.find_last_of("/") + 1);

	CxImage** img = new CxImage*[iImgCount];
	if (img == NULL) {
		cout << "new Cximage error!" << endl;
		return;
	}
	std::wstring stemp;
	LPCWSTR PicName;
	for (int i = 0; i < iImgCount; i++) {
		string tmp1;
		tmp1 = strTmp + strImgSets[i];
		stemp = s2ws(tmp1); // Temporary buffer is required
		PicName = stemp.c_str();
		img[i] = new CxImage;
		img[i]->Load(PicName, CXIMAGE_FORMAT_BMP);
		//bpp = 1;	bpp = 4;			 bpp = 8;
		if (0 == img[i]->GetNumColors())
		{
			img[i]->DecreaseBpp(8, true);
		}		
	}

	CxIOFile hFile;
	stemp = s2ws(strGifName); // Temporary buffer is required
	PicName = stemp.c_str();

	string Method = "wb";
	std::wstring  stempmd = s2ws(Method);
	LPCWSTR wMethod = stempmd.c_str();
	bool BFlag = hFile.Open(PicName, wMethod);

	CxImageGIF multiimage;

	multiimage.SetLoops(-1);
	multiimage.SetFrameDelay(300);
	multiimage.SetDisposalMethod(2);
	multiimage.Encode(&hFile, img, iImgCount, false, false);

	hFile.Close();

	delete[] img;
}

main测试代码:

	string strImgPath = "img/*.bmp";

	string strGifName = "img/test.gif";
	encoding_gif(strImgPath, strGifName);

测试结果是可以生成gif图片。再次表示感谢!


中途有个事情说下:在编译测试的过程中有个错误提示

 
cximage.lib(ximapsd.obj) : error LNK2001: 无法解析的外部符号 _psd_image_free 
cximage.lib(ximapsd.obj) : error LNK2019: 无法解析的外部符号 _psd_main_loop
解决方案:
libdcr.lib
libpsd.lib
将这两个包括进来就可以了。

三、CreateGIF

Csdn上资源:http://download.csdn.net/detail/iamshuke/2567835

非常感谢!若有问题,请随时联系。

本程序是用基于MFC的,对于我来使用,我不用MFC

其中重要的文件,其他的都是调用过程:

主要函数贴下:

BOOL GetData(HBITMAP hBmp,BYTE **ppPalette,BYTE **ppData,BYTE *pBitsPixel,int *pWidth,int *pHeight);

void CreateGIFHeard(CFile &file,WORD nImageWidth,WORD nImageHeight,BYTE bitsPixel);

void AddImageToGIF(CFile &file,BYTE *pData,BYTE *palette,WORD nImageWidth,WORD nImageHeight,BYTE bitsPixel,WORD nDelay,
				   short int nTransparentColorIndex);

void CloseGIF(CFile &file);

 --------------------------------------

若有问题,请随时联系!

非常感谢各位!  

原文地址:https://www.cnblogs.com/qitian1/p/6461964.html