How to create Photoshop layer masks from pixel data in UXP plugin (Lab Color Mode)?

Problem

I’m developing a Photoshop UXP plugin that needs to create Lab Fill Layers with masks based on arbitrary pixel data (Uint8Array with 0-255 values). Geometric selections work perfectly, but I cannot convert custom pixel data into masks.

Environment:

  • Photoshop UXP Plugin (API version without putSelectionFromPixels())
  • Document mode: Lab Color
  • Target: Fill Layers (contentLayer/solidColorLayer) with masks from pixel data

What Works

This approach using geometric selections works flawlessly:

// Create geometric selection
await doc.selection.selectEllipse(bounds, constants.SelectionType.REPLACE);

// Create Fill Layer + mask in one call
await action.batchPlay([
{ “_obj”: “make”, “target”: { “_ref”: “contentLayer” }, “using”: { /* solidColorLayer */ } },
{ “_obj”: “make”, “new”: { “_class”: “mask” }, “using”: { “_enum”: “userMaskEnabled”, “_value”:
“revealSelection” } }
], { “synchronousExecution”: true });

Result: Perfect mask - circle visible, rest masked.

What I Need

Convert this to a mask:

const maskData = new Uint8Array(width * height);
// Populate with 255 (visible) or 0 (masked)
for (let i = 0; i < maskData.length; i++) {
maskData[i] = /* calculation */ ? 255 : 0;
}

Failed Approaches

  1. Direct mask write with imaging.putPixels({targetMask: true})
    • Tried Grayscale and Lab formats
    • Error: “target sheet is not a pixel sheet” (Fill Layers don’t support this)
  2. Temp layer + Color Range selection
    • Write pixel data to temp layer, use Color Range to select white pixels
    • Problem: Selects everything - resulting mask is all white
  3. Temp layer + transparency selection
    • Load transparency as selection
    • Problem: Same result - selects everything
  4. imaging.putSelectionFromPixels()
    • Error: API doesn’t exist in my UXP version

Question

How can I convert Uint8Array pixel data into a layer mask for a Lab Fill Layer in Photoshop UXP?

I need one of these solutions:

  • Convert pixel data → selection → use working revealSelection approach
  • Write pixel data directly to Fill Layer’s mask
  • Alternative workflow that achieves the same result

The revealSelection approach works perfectly with geometric selections - I just need to create selections from pixel data instead.

Does this works on RGB? If so, you could temporary change it to RGB, do the mask thing and then convert back to LAB. Proper solution? I dunno but it’ll be a workaround to make it work so you can move on with your development and not get stuck on that.

Doesn’t work in RGB mode either.

I made a solution that works both RGB and LAB:

I splitted the code into two blocks so we can see the colors as If I paste it in one block it shows up white I dunno why, but here’s it is, try it out, it worked for me:

await createMaskFromAlphaBuffer();

async function createMaskFromAlphaBuffer(alphaBuffer) {
   await executeAsModal(async () => {
     const doc = app.activeDocument;
     const docW = doc.width;
     const docH = doc.height;

     // alphaBuffer goes here... Make sure it is the size of your document
     // you can override the new Uint8Array()... if you pass a Uint8Array here
     const pixels = new Uint8Array(docW * docH); 

     for (let i = 0; i < pixels.length; i++) {
        pixels[i] = 255// White pixels just to have something, Add your mask pixels here / computation...
     }


    const options = {
        width: doc.width,
        height: doc.height,
        components: 1,
        colorProfile: "Dot Gain 20%",
        colorSpace: "Grayscale"
    }

    const imageData = await imaging.createImageDataFromBuffer(pixels, options);
    await imaging.putLayerMask({
        imageData: imageData,
        documentID: app.activeDocument.id,
        layerID: app.activeDocument.activeLayers[0].id,
        commandName: "Save Pixels in layer"
    });

    await core.redrawDocument({ documentID: doc.id });
     imageData.dispose(); // Release memory before garbage collector to speed up things

}

Thank you so much. This is exactly what I need. I will be trying it out later today.

Thanks for the suggestion! I am not able to make it work. Maybe I am missing something. imaging.putLayerMask() does not exist in Photoshop UXP - attempting to call it throws “Error: Unsupported napi type”.

I also tested imaging.putPixels({ targetMask: true }) which DOES exist, but it only works on pixel layers. When you try to write mask data to a Fill Layer (which is a procedural/adjustment layer, not a pixel buffer), it fails with “Error: target sheet is not a pixel sheet”.

The only working approach I found for Fill Layers with custom masks is the selection-based method:

  1. Create temp pixel layer with RGBA data (alpha channel = mask)
  2. Load transparency as selection (batchPlay “set selection to transparencyEnum”)
  3. Delete temp layer
  4. Create Fill Layer + mask in single batchPlay call using revealSelection
  5. Clear selection

This works because revealSelection is part of Photoshop’s native selection-to-mask workflow, which works on all layer types. It’s slower (~500-800ms per layer due to temp layer creation), but it’s reliable.

Tested in Photoshop 2025.x, UXP API v2.

I did the code with the latest Photoshop version, if you stick to the latest PS version you’ll make sure to have all the API features to date.

I did it on PS 2026 ( v27.2.0 )