Skip to main content
Inspiring
January 28, 2024
Answered

Random clipping masks script

  • January 28, 2024
  • 2 replies
  • 651 views

Is there a way to load random images (jpeg) from a folder on my desktop and apply them to the selected shapes as a clipping masks? And every time i run the script it would change the result.

This topic has been closed for replies.
Correct answer Sergey Osokin
//@target illustrator

// Main function
function main() {
  var extList = ['jpeg', 'jpg']; // Supported file formats
  var isInclSubfol = true; // Get files from subfolders
  var isToCenter = false; // Align image to mask center
  var filesPath = decodeURIComponent(Folder.desktop + '/images'); // Source folder

  if (!documents.length) {
    return;
  }

  if (!app.selection.length || app.selection.typename === 'TextRange') {
    return;
  }

  var doc = app.activeDocument;
  var docSel = app.selection;
  var length = docSel.length;
  var files = getFolderFiles(Folder(filesPath), extList, isInclSubfol);
  var randomFiles = getRandomElements(files, length);
  var mask, img;

  for (var i = 0; i < length; i++) {
    mask = docSel[i];
    if (mask.typename !== 'PathItem' && mask.typename !== 'CompoundPathItem') continue;

    img = doc.placedItems.add();
    img.file = new File(randomFiles[i]);
    img.name = randomFiles[i].name.replace(/\.[^\.]+$/, '');
    
    img.move(mask, ElementPlacement.PLACEAFTER);

    if (isToCenter) {
      setCenterPosition(img, mask);
    } else {
      setRandomRelativePosition(img, mask);
    }

    img.selected = true;
    mask.selected = true;
    app.executeMenuCommand('makeMask');

    app.selection = [];
  }

  app.redraw();
}

function getFolderFiles(dir, ext, isInclSubfol) {
  var fList = dir.getFiles();
  var regexp = new RegExp(ext.join('|'));
  var arr = [];

  for (var i = 0, len = fList.length; i < len; i++) {
    var f = fList[i];
    if (isInclSubfol && f instanceof Folder) {
      arr = arr.concat(getFolderFiles(f, ext, isInclSubfol));
    } else if (f instanceof File) {
      var name = f.name.toLowerCase();
      // Ignore macOS hidden files
      if (!/^\._|ds_store/i.test(name)
          && regexp.test(/\.[^\.]+$/g.exec(name)[0])) {
        arr.push(f);
      }
    }
  }

  return arr;
}

function getRandomElements(arr, num) {
  var shuffled = arr.slice(0);
  var j, tmp;
  var result = [];

  if (num > arr.length) {
    for (var i = 0; i < num; i++) {
      var index = Math.floor(Math.random() * arr.length);
      result.push(arr[index]);
    }
  } else {
    for (var i = shuffled.length - 1; i > 0; i--) {
      j = Math.floor(Math.random() * (i + 1));
      tmp = shuffled[j];
      shuffled[j] = shuffled[i];
      shuffled[i] = tmp;
    }
  
    result = shuffled.slice(0, num);
  }

  return result;
}

function setCenterPosition(a, b) {
  var top = b.top - ((b.height / 2) - (a.height / 2));
  var left = b.left + (b.width / 2) - (a.width / 2);
  a.top = top;
  a.left = left;
}

function setRandomRelativePosition(a, b) {
  var bndsB = b.geometricBounds;
  var minX = bndsB[0];
  var maxY = bndsB[1];
  var maxX = bndsB[2] - a.width;
  var minY = bndsB[3] + a.height;
  
  a.position = [
    Math.random() * (maxX - minX) + minX,
    Math.random() * (maxY - minY) + minY
  ];
}


// Run script
try {
  main();
} catch (e) {}

2 replies

Sergey Osokin
Sergey OsokinCorrect answer
Inspiring
January 29, 2024
//@target illustrator

// Main function
function main() {
  var extList = ['jpeg', 'jpg']; // Supported file formats
  var isInclSubfol = true; // Get files from subfolders
  var isToCenter = false; // Align image to mask center
  var filesPath = decodeURIComponent(Folder.desktop + '/images'); // Source folder

  if (!documents.length) {
    return;
  }

  if (!app.selection.length || app.selection.typename === 'TextRange') {
    return;
  }

  var doc = app.activeDocument;
  var docSel = app.selection;
  var length = docSel.length;
  var files = getFolderFiles(Folder(filesPath), extList, isInclSubfol);
  var randomFiles = getRandomElements(files, length);
  var mask, img;

  for (var i = 0; i < length; i++) {
    mask = docSel[i];
    if (mask.typename !== 'PathItem' && mask.typename !== 'CompoundPathItem') continue;

    img = doc.placedItems.add();
    img.file = new File(randomFiles[i]);
    img.name = randomFiles[i].name.replace(/\.[^\.]+$/, '');
    
    img.move(mask, ElementPlacement.PLACEAFTER);

    if (isToCenter) {
      setCenterPosition(img, mask);
    } else {
      setRandomRelativePosition(img, mask);
    }

    img.selected = true;
    mask.selected = true;
    app.executeMenuCommand('makeMask');

    app.selection = [];
  }

  app.redraw();
}

function getFolderFiles(dir, ext, isInclSubfol) {
  var fList = dir.getFiles();
  var regexp = new RegExp(ext.join('|'));
  var arr = [];

  for (var i = 0, len = fList.length; i < len; i++) {
    var f = fList[i];
    if (isInclSubfol && f instanceof Folder) {
      arr = arr.concat(getFolderFiles(f, ext, isInclSubfol));
    } else if (f instanceof File) {
      var name = f.name.toLowerCase();
      // Ignore macOS hidden files
      if (!/^\._|ds_store/i.test(name)
          && regexp.test(/\.[^\.]+$/g.exec(name)[0])) {
        arr.push(f);
      }
    }
  }

  return arr;
}

function getRandomElements(arr, num) {
  var shuffled = arr.slice(0);
  var j, tmp;
  var result = [];

  if (num > arr.length) {
    for (var i = 0; i < num; i++) {
      var index = Math.floor(Math.random() * arr.length);
      result.push(arr[index]);
    }
  } else {
    for (var i = shuffled.length - 1; i > 0; i--) {
      j = Math.floor(Math.random() * (i + 1));
      tmp = shuffled[j];
      shuffled[j] = shuffled[i];
      shuffled[i] = tmp;
    }
  
    result = shuffled.slice(0, num);
  }

  return result;
}

function setCenterPosition(a, b) {
  var top = b.top - ((b.height / 2) - (a.height / 2));
  var left = b.left + (b.width / 2) - (a.width / 2);
  a.top = top;
  a.left = left;
}

function setRandomRelativePosition(a, b) {
  var bndsB = b.geometricBounds;
  var minX = bndsB[0];
  var maxY = bndsB[1];
  var maxX = bndsB[2] - a.width;
  var minY = bndsB[3] + a.height;
  
  a.position = [
    Math.random() * (maxX - minX) + minX,
    Math.random() * (maxY - minY) + minY
  ];
}


// Run script
try {
  main();
} catch (e) {}

Zipo4323Author
Inspiring
January 29, 2024

Wow! Thank you very much!!! It works perfectly!

Sergey Osokin
Inspiring
January 28, 2024

Do you think imported JPEGs should be resized to fit the clipping mask (selected shape) size and centered?

Zipo4323Author
Inspiring
January 28, 2024

It would be great if they would be centered, or even greater if they would be randomly located within the clipping mask limits, so that the edges of the jpeg would not be visible. But the size should stay the same. Thank you for the question!

Sergey Osokin
Inspiring
January 29, 2024

If you have a JPG that is smaller than the mask, then without resizing the JPG, there will be empty areas. Do you create shapes for masks knowing the exact width and height dimensions of JPGs so that vector shapes are no larger than them?