C++生成GIF小结
声明:所有权利保留。
转载必须说明出处:http://blog.csdn.net/cartzhang/article/details/44020175
近来需要把BMP或Kinect的内存图片多张合成为小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位版本,所以使用了x64的release模式。有个与mfc相关的编译不过,直接无视了,本人用不上mfc。
生成的为lib的静态库。
我把所需要的头文件和静态库拷贝的到自己建立的目录下和各个对应的文件夹下,如图:
Include 文件从CXimage中拷贝头文件,lib库文件为编译后生成的x64文件里面的,包括Debug版本和Release版本。
网上找了个代码,对CXimage的GIF写了两个函数。本人在基础上稍微添加和修改了代码。
其实主要是处理相关文件夹方便来调用的。非常感谢网友提供,头文件和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图片。再次表示感谢!
中途有个事情说下:在编译测试的过程中有个错误提示
libdcr.liblibpsd.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);
--------------------------------------
若有问题,请随时联系!
非常感谢各位!
C++生成GIF小结的更多相关文章
- VS2017中 C# dll引用(C生成dll,C++生成dll)小结 - 简书
原文:VS2017中 C# dll引用(C生成dll,C++生成dll)小结 - 简书 dll引用小结 一.dll与应用程序 动态链接库(也称为DLL,即为“Dynamic Link Library” ...
- 全局唯一性ID生成方法小结
全局ID通常要满足分片的一些要求:1 不能有单点故障.2 以时间为序,或者ID里包含时间.这样一是可以少一个索引,二是冷热数据容易分离.3 可以控制ShardingId.比如某一个用户的文章要放在同一 ...
- (引用)Python 生成随机数小结
转载:http://blog.csdn.net/shuaijiasanshao/article/details/51339438
- Oracle分区索引
索引与表类似,也可以分区: 分区索引分为两类: Locally partitioned index(局部分区索引) Globally partitioned index(全局分区索引) 下面就来详细解 ...
- CUDA 程序中的同步
前言 在并发,多线程环境下,同步是一个很重要的环节.同步即是指进程/线程之间的执行顺序约定. 本文将介绍如何通过共享内存机制实现块内多线程之间的同步. 至于块之间的同步,需要使用到 global me ...
- 使用 CUBLAS 库给矩阵运算提速
前言 编写 CUDA 程序真心不是个简单的事儿,调试也不方便,很费时.那么有没有一些现成的 CUDA 库来调用呢? 答案是有的,如 CUBLAS 就是 CUDA 专门用来解决线性代数运算的库. 本文将 ...
- CUDA 标准编程模式
前言 本文将介绍 CUDA 编程的基本模式,所有 CUDA 程序都基于此模式编写,即使是调用库,库的底层也是这个模式实现的. 模式描述 1. 定义需要在 device 端执行的核函数.( 函数声明前加 ...
- Cublas矩阵加速运算
前言 编写 CUDA 程序真心不是个简单的事儿,调试也不方便,很费时.那么有没有一些现成的 CUDA 库来调用呢? 答案是有的,如 CUBLAS 就是 CUDA 专门用来解决线性代数运算的库. 本文将 ...
- .NET Core开发日志——Entity Framework与PostgreSQL
Entity Framework在.NET Core中被命名为Entity Framework Core.虽然一般会用于对SQL Server数据库进行数据操作,但其实它还支持其它数据库,这里就以Po ...
随机推荐
- 纯C++实现的HTTP请求封装(POST/GET)
纯C++实现的HTTP请求(POST/GET),支持windows和linux, 进行简单的封装, 方便调用.实现如下: #include "HttpConnect.h" #ifd ...
- HTML基础第十二讲---链接标志
转自:https://i.cnblogs.com/posts?categoryid=1121494 没有链接,WWW将失去存在的意义!WWW之所以受欢迎,乃在于她除了有精美的图文之外,更有方便且多样化 ...
- js取对象的属性值循环
var data = {name: "liuyang", job: "web", age: "27"} Object.keys(data). ...
- Python数据结构同Json类型数据相互转换的用法
在做Python接口自动化的时候,经常要用到Python数据结构同Json类型数据相互转换来供我们做进一步的验证提供数据,在此做个记录和总结 Python数据结构同Json类型数据相互转换的函数有:j ...
- jquery选择器里面也可以包含变量字符串
$("#"+uid).text(text);//jquery的选择器是可以放变量字符串的,同样是拼接字符串.
- (转)高强度密码管理软件KeePass使用详解
转自:http://www.ruancan.com/ 算下来,你接触电脑有多久了?从第一次上网,到今天,你一共申请了多少个网站或者软件的帐号?相信这是一个几乎无人能够回答的问题. 无数人面临着这两个问 ...
- LoadRunner--录制手机APP脚本
通过LR录制手机脚本的方式有三种: 1)通过安卓模拟器录制: 2)通过抓包录制: 3)通过代理方式录制: 本文使用第二种方式进行录制,首先需要先安装LoadRunner11测试工具,然后安装lr录制A ...
- UVA 11090 - Going in Cycle!! SPFA
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
- 10.7 android输入系统_Dispatcher线程情景分析_Reader线程传递事件和dispatch前处理
android输入系统C++最上层文件是com_android_serve_input_InputManagerService.cpp global key:按下按键,启动某个APP可以自己指定,修改 ...
- 10.1、android输入系统_必备Linux编程知识_inotify和epoll
1. inotify和epoll 怎么监测键盘接入与拔出? (1)hotplug机制:内核发现键盘接入/拔出==>启动hotplug进程==>发消息给输入系统 (2)inotify机制:输 ...