笔记:实现数组排列组合图片合成,做一个NFT生成器! 308 次阅读

前言

NFT是前两年火起来的,被大家称为是去中心化的非同质化代币,是具有唯一性的数字资产加密货币令牌,并且是可以买卖的!

这是一场资本家的狂欢泡沫还是致富风口?

咱不知道,就是单纯的最近想自己玩一玩,弄一套上架到NFT交易平台上去看看2333..

然后自己p好了素材,苦于找不到批量生成工具,找了一圈发现网络上有很多js和python的脚本。

但是我自己下载下来运行后发现,不是缺这个模块就是缺那个环境没有部署,更难受的是安装模块还不成功!

最后就自己在Android上去实现了

下面直接看怎么实现的:

Android实现图片合成

数组排列组合

先把每个素材保存到单独的数组里,然后把全部数组合并为一个数组:

1
2
3
4
5
6
7

allList.add(arr_1);
allList.add(arr_2);
allList.add(arr_3);
...
...

排列组合:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

/**
* 算法,非递归计算所有组合
* @param inputList 所有数组的列表
* allList_new:排列组合后的新数组
*
* */
public void def_calculateCombination(List<List<String>> inputList) {
List<Integer> combination = new ArrayList<Integer>();
allList_new.clear();
int n=inputList.size();
for (int i = 0; i < n; i++) {
combination.add(0);
}
int i=0;
boolean isContinue=false;
do{
List<String> List = new ArrayList<>();
//打印一次循环生成的组合
for (int j = 0; j < n; j++) {
Log.e("=========>>>", "" + inputList.get(j).get(combination.get(j)));
List.add("" + inputList.get(j).get(combination.get(j)));
}
Log.e("=========", "====下一组====");
allList_new.add(List);

i++;
combination.set(n - 1, i);
for (int j = n - 1; j >= 0; j--) {
if (combination.get(j) >= inputList.get(j).size()) {
combination.set(j, 0);
i = 0;
if (j - 1 >= 0) {
combination.set(j - 1, combination.get(j - 1) + 1);
}
}
}
isContinue = false;
for (Integer integer : combination) {
if (integer != 0) {
isContinue = true;
}
}
}while (isContinue);
}

图片合成

图片合成,返回合成后的新图片Bitmap:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

/**
*
* @param background 背景图
* @param body 前景图
* @return
*/
public Bitmap def_combineBitmap(Bitmap background, Bitmap body) {
if (background == null) {
return null;
}
int bgWidth = background.getWidth();
int bgHeight = background.getHeight();
/*
int fgWidth = body.getWidth();
int fgHeight = body.getHeight();
*/
Bitmap newmap = Bitmap.createBitmap(bgWidth, bgHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newmap);
//添加每个素材图片到画布
if (background != null) {
canvas.drawBitmap(background, 0, 0, null);//参数2和3是设置贴图的xy坐标位置
}
if (body != null) {
canvas.drawBitmap(body, 0, 0, null);
}
//更多素材可以继续在后面添加
canvas.save();
canvas.restore();
return newmap;
}

保存图片到手机

保存图片到sd卡指定目录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

public void def_savePic(Bitmap btImage) {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
FileOutputStream out = null;
// 获取SDCard指定目录下
String sdCardDir = Environment.getExternalStorageDirectory() + "/NFT/";
File dirFile = new File(sdCardDir); //目录转化成文件夹
if (!dirFile .exists()) { //如果不存在,那就建立这个文件夹
dirFile .mkdirs();
}
File file = new File(sdCardDir, "NFT" + System.currentTimeMillis() + ".png");// 在SDcard的目录下创建图片文,以当前时间为其命名
try {
out = new FileOutputStream(file);
btImage.compress(Bitmap.CompressFormat.PNG, 100, out);
//System.out.println("___保存到_sd_指定目录文件夹___");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
//Toast.makeText(MainActivity.this, "保存已经至" + sdCardDir + "目录文件夹下", Toast.LENGTH_SHORT).show();
}
}

保存图片需要SD卡写入的权限,别忘了在 AndroidManifest.xml 中添加!

附加:系统文件管理器选择文件素材并返回路径Uri

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

//存放需要过滤的类型的类
public class MimeType {
/*
public static final String DOC = "application/msword";
public static final String DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
public static final String XLS = "application/vnd.ms-excel";
public static final String XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
public static final String PPT = "application/vnd.ms-powerpoint";
public static final String PPTX = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
public static final String PDF = "application/pdf";
public static final String PNG = "image/png";
*/
public static final String JPG = "image/*";
}

//选择文件
private void def_performFileSearch() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
//允许多选 长按多选
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
//不限制选取类型
intent.setType("*/*");

//如果想给选择器添加过滤的文件类型,只需要添加如下代码就可以了
String[] mimeTypes = {
/*
MimeType.DOC,
MimeType.DOCX,
MimeType.PDF,
MimeType.PPT,
MimeType.PPTX,
MimeType.XLS,
MimeType.XLSX,
MimeType.PNG,*/
MimeType.JPG
};
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);

startActivityForResult(intent, 1); //第二个参数必须是大于0的,才会响应onActivityResult()回调函数
}

//接收选择文件后的返回值
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 1:
if (resultCode == Activity.RESULT_OK && data != null) {
//单选选了一个文件后返回
if (data.getData() != null) {
String uri = def_handleSingleDocument(data);
//数据uri
} else {
//多选后返回
ClipData clipData = data.getClipData();
if (clipData != null) {
Uri[] uris = new Uri[clipData.getItemCount()];
for (int i = 0; i < clipData.getItemCount(); i++) {
uris[i] = clipData.getItemAt(i).getUri();
}
//数据uris
}
}
}
break;
}
}

//将uri转换为我们需要的path,多选类似
private String def_handleSingleDocument(Intent data) {
Uri uri = data.getData();
String filePath = null;
try {
filePath = MyFileUtils.getPath(this, uri);
} catch (Exception e) {}
return filePath;
}

基本上,通关上面这些关键函数,就完全可以实现自己做一个“NFT生成器”App了。

结语

(PS:NFT还会跟当年的比特币那样火起来吗,还是泡沫破灭呢,值得深思emmm…)

OK,今天就这样,感谢阅读。

么么哒~~

上一篇 避坑:小程序canvas绘制不显示,动态请求图片报Unhandled promise rejection错误解决
下一篇 Android实现帧动画动态设置播放时间间隔
感谢您的支持!
微信赞赏码 微信赞赏
支付宝赞赏码 支付宝赞赏