Shape Masking

Apply shape masks to images for creative effects.

Applying a Mask

Using Presets

const raster = app.imageGroup.children[0];

// Circle mask
const masked = app.imageTools.applyMask(raster, 'circle');

// Star mask with options
const starMasked = app.imageTools.applyMask(raster, 'star', {
  points: 6,
  innerRadius: 0.3
});

Available Mask Presets

Preset Description Options
circle Circular mask centered on image -
ellipse Oval mask filling image bounds -
star Star shape points, innerRadius
triangle Equilateral triangle -
hexagon Six-sided polygon -
heart Heart shape -
rounded Rounded rectangle cornerRadius

Using Custom Paths

// Create a custom path
const customPath = new paper.Path();
customPath.moveTo(0, 50);
customPath.lineTo(50, 0);
customPath.lineTo(100, 50);
customPath.lineTo(50, 100);
customPath.closePath();

// Apply as mask
const masked = app.imageTools.applyMask(raster, customPath);

Mask Options

Feathered Edges

const masked = app.imageTools.applyMask(raster, 'circle', {
  feather: 10  // Soft edge radius
});

Star Options

const masked = app.imageTools.applyMask(raster, 'star', {
  points: 8,       // Number of points
  innerRadius: 0.4 // Inner radius ratio (0-1)
});

Rounded Rectangle Options

const masked = app.imageTools.applyMask(raster, 'rounded', {
  cornerRadius: 20  // Corner radius in pixels
});

Removing a Mask

const originalRaster = app.imageTools.removeMask(maskedGroup);

Events

window.addEventListener('maskApplied', (e) => {
  console.log('Mask applied:', e.detail.maskType);
  console.log('Group:', e.detail.group);
});

Masked Item Structure

When you apply a mask, the raster becomes a clipped group:

maskedGroup.className    // 'Group'
maskedGroup.clipped      // true
maskedGroup.data.masked  // true
maskedGroup.data.maskType // 'circle', 'star', etc.
maskedGroup.children[0]  // The mask path
maskedGroup.children[1]  // The raster

Example: Profile Picture Style

// Create circular profile picture
async function createProfilePicture(file) {
  // Upload
  const entry = await app.imageTools.uploadImage(file);

  // Place at center
  const raster = await app.imageTools.placeImage(entry.id, {
    position: [app.view.center.x, app.view.center.y],
    maxWidth: 200,
    maxHeight: 200
  });

  // Crop to square
  app.imageTools.startCrop(raster, { aspectRatio: '1:1' });
  const cropped = await app.imageTools.applyCrop();

  // Apply circle mask
  const profile = app.imageTools.applyMask(cropped, 'circle');

  return profile;
}
// Apply different masks to copies of an image
async function createShapeGallery(imageId) {
  const shapes = ['circle', 'star', 'heart', 'hexagon', 'triangle'];
  const spacing = 150;

  for (let i = 0; i < shapes.length; i++) {
    const raster = await app.imageTools.placeImage(imageId, {
      position: [100 + i * spacing, 300],
      maxWidth: 100,
      maxHeight: 100
    });

    app.imageTools.applyMask(raster, shapes[i]);
  }
}