准备工作
因为我们要调用的是腾讯的远程API滤镜接口,因此要先注册账号(注册地址),然后创建应用程序,进入控制台,点击“创建应用”即可完成创建。再查看应用信息,拷贝app_id和app_key,后面要用到。如下图所示:
![](https://raw.githubusercontent.com/FredLyu/FigureBed-Hector/master/BlogFigure/chuangjian.png)
这里也给出腾讯AI滤镜的开发文档地址(开发文档),大家可以先自己了解一下,然后再往下看。
核心代码讲解
总共有天天P图和AI Lab两个滤镜API接口,不过参数基本相同,都是htpp post请求。本文是基于Unity2018.3.0进行开发,将使用UnityWebRequest进行post请求。API 具体的请求参数如下:
![](https://raw.githubusercontent.com/FredLyu/FigureBed-Hector/master/BlogFigure/ptu.png)
![](https://raw.githubusercontent.com/FredLyu/FigureBed-Hector/master/BlogFigure/appinfo.png)
首先是time_stamp,int类型,根据字段描述,可以知道是请求时间戳,以秒为单位,因此只要算出当前时间距1970.01.01:00:00:00的秒数就好,具体代码如下:
private string GetUnixTimestamp()
{
//获取时间
TimeSpan timeSpan = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0);
//将时间转换为以秒为单位,因此是64位的整型值
return Convert.ToInt64(timeSpan.TotalSeconds).ToString();
}
然后是image参数,string类型,要求是base64编码数据(这是什么鬼)。刚看到,我也是一头雾水,通过查阅资料发现用C#实现就是先把图片转换为byte数组,然后再转换为base64字符串即可。具体代码如下:
private string Bytes2Base64(byte[] bytes)
{
string base64 = Convert.ToBase64String(bytes);
int mod = base64.Length % 4;
if(mod > 0)
{
base64 += new string('=', 4 - mod);
}
return base64;
}
不过有个坑就是,通过在线工具转换的base64字符串长度是4的整数倍,不足的用"="补足了。因此上面的代码进行了4的倍数判断并自动补足。
最后一个参数是sign,授权密钥,比较头疼,不过看过描述之后,觉得也还好。授权描述如下:
![](https://raw.githubusercontent.com/FredLyu/FigureBed-Hector/master/BlogFigure/sign.png)
不过问题又来了,什么是URL编码?查阅资料,最后发现Unity中实现该算法,调用UnityWebRequest.EscapeURL(string)即可,但对得到的字符串要转换为大写字母。具体实现代码如下:
private string ConvertURLEncode(string str, bool isImage=false)
{
string urlCode = UnityWebRequest.EscapeURL(str);
if (isImage)
{
string str1 = UnityWebRequest.EscapeURL("+");
string str2 = UnityWebRequest.EscapeURL("/");
string str3 = UnityWebRequest.EscapeURL("=");
urlCode = urlCode.Replace(str1, str1.ToUpper());
urlCode = urlCode.Replace(str2, str2.ToUpper());
urlCode = urlCode.Replace(str3, str3.ToUpper());
return urlCode;
}
else
return urlCode;
}
对于上面的代码,大家会发现为什么对于图片的base64字符没有直接进行URL编码。这是因为URL编码只对部分字符进行编码,对数字和英文字母不进行编码(具体请看这里URL编码)。而且如果我们对整个base64字符串进行URL编码,会消耗相当长的一段时间。因此我采用了如上的代码实现URL编码。
URL编码我们已经会了,接下来就是对得到的字符串进行MD5运算,得到sign授权字符串。而C#刚好实现了MD5加密算法,具体代码如下:
private string GetMD5Str(string str)
{
byte[] bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
//转换为大写字母字符串
return BitConverter.ToString(bytes).ToUpper().Replace("-", "");
}
所有的参数我们都已经准备好了,那就可以进行Http post请求了,不过请求成功返回什么样的结果呢?具体可以看文档的描述,如下图所示:
![](https://raw.githubusercontent.com/FredLyu/FigureBed-Hector/master/BlogFigure/result.png)
[Serializable]
public class Data
{
public string image;
}
[Serializable]
public class ImageData
{
public int ret;
public string msg;
public Data data;
}
最后一点就是对于AI Lab的API接口参数对了一个session_id参数,对于的是string类型,作用是请求id,只要保证每次请求值与之前不一样即可。下面是post请求表单和sign计算代码:
private WWWForm GetPostForm(byte[] imgBytes, FilterType filterType, int filterId)
{
//将图片转换为Base64字符串
string imgStr = Bytes2Base64(imgBytes);//图片转为JPG格式的字符串,减小图片大小
//获取时间戳
string timeStamp = GetUnixTimestamp();
//设置请求字段
WWWForm form = new WWWForm();
form.AddField("app_id", int.Parse(app_id));
form.AddField("filter", filterId);
form.AddField("image", imgStr);
form.AddField("time_stamp", int.Parse(timeStamp));
form.AddField("nonce_str", timeStamp);
//获取加密原字符串,对<key,value>按key升序排列
string originalStr = "app_id=" + app_id +
"&filter=" + filterId +
"&image=" + ConvertURLEncode(imgStr, true) +
"&nonce_str=" + timeStamp;
if (filterType == FilterType.TTPTUFilter)
{
originalStr += "&time_stamp=" + timeStamp +
"&app_key=" + app_key;
}
else
{
originalStr += "&session_id=" + timeStamp +
"&time_stamp=" + timeStamp +
"&app_key=" + app_key;
form.AddField("session_id", timeStamp);
}
form.AddField("sign", GetMD5Str(originalStr));
return form;
}
效果展示
![](https://raw.githubusercontent.com/FredLyu/FigureBed-Hector/master/BlogFigure/ptufilter.png)
![](https://raw.githubusercontent.com/FredLyu/FigureBed-Hector/master/BlogFigure/labfilter.png)
如有侵权,请联系删除!