PS在使用脚本生成nft艺术品的踩坑之旅
- 主要功能是生成一个 HashLips 艺术生成器,让用户可以选择生成多少图像、集合的名称和每个图像应该具有的不同特征数量的一个脚本。
- 第一个坑就是ps识别不出一些内置函数,例如 indexOf(),add(),includes().等等这些已经写好的方法,想使用就必须写一个辅助函数,在你需要用的地方调用这个辅助函数。
- 第二个坑就是在生成图片的时候,图层的命名不可以用中文,这会导致生成图片的Metadata不识别,导致写不到JSON中。
- 第三个坑也是中文的问题,脚本的一些注释必须使用英文,中文会报很离谱的错误
综上就是在使用脚本所遇到的坑人的地方
function indexOf(Array, element) {
for (var i = 0; i < Array.length; i++) {
if (Array[i] == element) {
return i
}
}
return -1;
}
function main() {
var continueConfirmation = confirm(
"You are about to use the HashLips art generator. Are you sure you want to continue?"
);
if (!continueConfirmation) return;
alert("Layers do not support Chinese naming")
var supply = prompt("How many images do you want to generate?", "10");
var name = prompt("What is the name of your collection?", "");
var numDifferences_x = prompt("How many different features should each image have?", "3");
alert(
supply +
" images will be generated, so sit back relax and enjoy the art being generated."
);
var groups = app.activeDocument.layerSets;
resetLayers(groups);
var parts = [];
for (var i = 0; i < groups.length; i++) {
var arr = [];
for (var j = 0; j < groups[i].layers.length; j++) {
arr.push(j)
}
parts.push(arr);
}
var numDifferences = numDifferences_x;
var generatedImages = generateImages(parts, supply, numDifferences);
for (var i = 0; i < generatedImages.length; i++) {
var obj = {};
obj.name = name + "#" + (i + 1);
obj.image = "To be replaced";
obj.edition = i + 1;
obj.attributes = [];
for (var j = 0; j < generatedImages[i].length; j++) {
var groupidx = j;
var layeridx = generatedImages[i][j];
groups[groupidx].layers[layeridx].visible = true;
obj.attributes.push({
trait_type: groups[groupidx].name,
value: groups[groupidx].layers[layeridx].name
})
}
saveMetadata(obj, name);
saveImage(obj, name);
resetLayers(groups);
}
alert("Generation process is complete.");
}
function resetLayers(_groups) {
for (var i = 0; i < _groups.length; i++) {
_groups[i].visible = true;
for (var j = 0; j < _groups[i].layers.length; j++) {
_groups[i].layers[j].visible = false;
}
}
}
function saveImage(_obj, _name) {
var saveFile = new File(toFolder("build/" + _name + "/images") + "/" + _obj.edition + ".png");
exportOptions = new ExportOptionsSaveForWeb();
exportOptions.format = SaveDocumentType.PNG;
exportOptions.PNG24 = false;
exportOptions.transparency = true;
exportOptions.interlaced = false;
app.activeDocument.exportDocument(
saveFile,
ExportType.SAVEFORWEB,
exportOptions
);
}
function saveMetadata(_data, _name) {
var file = new File(toFolder("build/" + _name + "/metadata") + "/" + _data.edition + ".json");
file.open("w");
file.write(JSON.stringify(_data));
file.close();
}
function toFolder(_name) {
var path = app.activeDocument.path;
var folder = new Folder(path + "/" + _name);
if (!folder.exists) {
folder.create();
}
return folder;
}
function generateImages(partsArray, _supply, _numDifferences) {
var images = [];
var repeatTimes = 0;
while (images.length < _supply) {
repeatTimes++;
if (repeatTimes > 5000) {
break;
}
var combination = [];
for (var i = 0; i < partsArray.length; i++) {
var midx = parseInt(Math.random() * partsArray[i].length);
combination.push(midx);
}
var canbePush = true;
for (var i = 0; i < images.length; i++) {
var existingCombination = images[i];
var differences = getDifferences(combination, existingCombination, _numDifferences);
if (differences < _numDifferences) {
canbePush = false;
break;
}
}
if (canbePush) {
repeatTimes = 0;
images.push(combination);
}
}
return images;
}
function getDifferences(combination1, combination2, diff) {
var differences = 0;
for (var i = 0; i < combination1.length; i++) {
if (combination1[i] !== combination2[i]) {
differences++;
if (differences >= diff) {
break;
}
}
}
return differences;
}
function compareArrays(arr1, arr2, diff) {
var count = 0;
for (var i = 0; i < arr1.length; i++) {
var diffBits = arr1[i] ^ arr2[i];
while (diffBits !== 0) {
if (diffBits & 1) {
count++;
if (count >= diff) {
return true;
}
}
diffBits >>= 1;
}
}
return false;
}
main();