ColorSampler trouble: .move works, but don't get new pixel color data

I am trying to pull sample pixel data from across an image. Sampled values in the following code indicates that the sampling position is being moved appropriately, but the red, blue, and green values remain exactly the same no matter what the position it is.

Any thoughts on what I’m doing wrong?

let width = layerBounds.width;
let height = layerBounds.height;

let NumSamples = 3;  // 10 samples along both height and width
let WidthIncremenet = Math.round((.9*width) / (NumSamples+1));
let HeightIncrement = Math.round((.9*height) / (NumSamples+1));

let RefColorData = Array(NumSamples * NumSamples * 4);   //  1=R 2=G 3=B 4=R

app.activeDocument.colorSamplers.add({ x: 1, y: 1 });

const cs = app.activeDocument.colorSamplers[0];

let z = 1;
let x = Math.round(WidthIncremenet / 2); let y = Math.round(HeightIncrement/2);

// Capture Reference image color samples
for (x = 10; x < width; x += WidthIncremenet) {
    for (y = 10; y < height; y += HeightIncrement) {
        cs.move({ x: x, y: y });
        RefColorData[z++] = cs.position.x;
        RefColorData[z++] = cs.position.y;
        RefColorData[z++] = cs.color.rgb.red;
        RefColorData[z++] = cs.color.rgb.green;
        RefColorData[z++] = cs.color.rgb.blue;
    }
}
app.activeDocument.colorSamplers.removeAll();

Representative RefColorData generated values; these are the values for pixel 1,1 specified in app.activeDocument.colorSamplers.add({ x: 1, y: 1 }), not from any of the cs.move({ x: x, y: y }).

  1. 1: 50
  2. 2: 50
  3. 3: 38.80155642023346
  4. 4: 0.28793774319066145
  5. 5: 208.7898832684825
  6. 6: 50
  7. 7: 275
  8. 8: 38.80155642023346
  9. 9: 0.28793774319066145
  10. 10: 208.7898832684825
  11. 11: 50
  12. 12: 500
  13. 13: 38.80155642023346
  14. 14: 0.28793774319066145
  15. 15: 208.7898832684825
  16. 16: 50
  17. 17: 725
  18. 18: 38.80155642023346
  19. 19: 0.28793774319066145
  20. 20: 208.7898832684825

It’s interesting that the cs.position.x and cs.position.y are updated by the cs.move, but not the cs.color.rgb.red etc.

Thanks,
John

It is not your fault. It is DOM issue and what low-level action manager code is available.

Problem with action manager (AM) is that you can’t get color sampler by ID… they don’t have the ID. You can’t even get them by index alone. But you can get all samplers in document.

So in order to get color every time correctly you would need to ask Document class for all color samplers pick correct index from array and pick correct color.

But this is not how it works under the hood. They way it works right now… it takes an array from AM… instantiate color samplers and sets color into private property of the ColorSampler instance… the color is stuck within instance forever and cannot be changed.

So right now the only way to get it right is to create new instance and get rid of the old one. Under the hood this will happen when you ask document for color sampler. So you could change it like this:

let width = layerBounds.width;
let height = layerBounds.height;

let NumSamples = 3;  // 10 samples along both height and width
let WidthIncremenet = Math.round((.9*width) / (NumSamples+1));
let HeightIncrement = Math.round((.9*height) / (NumSamples+1));

let RefColorData = Array(NumSamples * NumSamples * 4);   //  1=R 2=G 3=B 4=R

app.activeDocument.colorSamplers.add({ x: 1, y: 1 });

const samplers = app.activeDocument.colorSamplers // store proxy to save performance
let cs = samplers[0];

let z = 1;
let x = Math.round(WidthIncremenet / 2); let y = Math.round(HeightIncrement/2);

// Capture Reference image color samples
for (x = 10; x < width; x += WidthIncremenet) {
    for (y = 10; y < height; y += HeightIncrement) {
        cs = samplers[0]; // this is important... makes new instance under the hood
        cs.move({ x: x, y: y });
        RefColorData[z++] = cs.position.x;
        RefColorData[z++] = cs.position.y;
        RefColorData[z++] = cs.color.rgb.red;
        RefColorData[z++] = cs.color.rgb.green;
        RefColorData[z++] = cs.color.rgb.blue;
    }
}
app.activeDocument.colorSamplers.removeAll();

Would be great if Adobe could add better AM code so better DOM would be possible.

Btw yes position is updated… but the value does not come from PS Document.

Let me know if that works. I did not test the code.

Thanks very much, Jarda. That almost did it. I had to make one tweak to make the rgb data match the coordinates: for some reason I had to place cs.move({ x: x, y: y } BEFORE cs=samplers[0].

for (x = width1; x < width; x += WidthIncremenet) {
    for (y = height1; y < height; y += HeightIncrement) {
        cs.move({ x: x, y: y });
        cs = samplers[0];  // important to make new instance and reset colors
        RefColorData[z++] = cs.position.x;
        RefColorData[z++] = cs.position.y;
        RefColorData[z++] = cs.color.rgb.red;
        RefColorData[z++] = cs.color.rgb.green;
        RefColorData[z++] = cs.color.rgb.blue;
    }
}

Thanks again for your great help!
John

1 Like

A follow-up question, please: is it possible to specify the layer the colorSampler will sample?

Thanks,
John

Maybe with AM code, you could change the current tool option. But I warn you… it is not nice code :smiley:

Thanks Jarda, all try another approach first.
John