Questions about getPisxel

Hello!

I do not have much experience with UXP and English is not my first language, so please forgive me if I am writing in a text that is difficult to understand…

I am trying to create a plugin in Photoshop that will duplicate multiple layers individually in the same selection.
I have a selection on each active layer, so I was wondering if there is a way to duplicate the selection repeatedly on each active layer.
However, when I try to duplicate a layer based on a selection, the pixels are expaned to that area.

How can I modify it so that it does not expand?

Thank you!

await core.executeAsModal(async () => {
        try {
            const activeLayer = app.activeDocument.activeLayers[0];
            const newLayer = await app.activeDocument.layers.add();
            const selection = await imaging.getSelection({});
            const img = await imaging.getPixels({
                layerID: activeLayer.id,
                sourceBounds: selection.sourceBounds,
                colorSpace: "RGB",
                targetSize: {
                  height: selection.sourceBounds.bottom - selection.sourceBounds.top,
                  width: selection.sourceBounds.right - selection.sourceBounds.left
                }
            });
            const bufferImg = await img.imageData.getData({chunky: true});
            const components = img.imageData.components;
            const width = selection.sourceBounds.right - selection.sourceBounds.left;
            const height = selection.sourceBounds.bottom - selection.sourceBounds.top;
            const imageData = await imaging.createImageDataFromBuffer(bufferImg, {width:width, height: height, components: 4, colorSpace: "RGB"});
            await imaging.putPixels({
                layerID: newLayer.id,
                imageData: imageData,
                targetBounds: { "left": selection.sourceBounds.left, "top": selection.sourceBounds.top }
            });
        } catch (e) {
            console.log(e);
        }
    });

Maybe just for clarification, are you trying to 1) take the pixels from multiple layers and put them on new layers or 2) copy the pixels from one layer onto multiple different layers to replace what is on that layer, or 3) something else?

  1. and 2) could be accomplished using the batchPlay code from Alchemist, I think, as these two options sound like a copy-and-paste type maneuver.

Anthony, Thank you for your reply.

The function I want to create is exactly the method 1).

So I was actually developing with the batchPlay at the same time.

However, I wanted to know how to solve this question for future study.

Self resolved.
After duplicating the layer, I resized the selected area to the correct size by using the layer’s scale function to resize it to the correct size.
After that, I moved the newly created layer to the correct position and got the same behavior as when copying and pasting the area.

@AnthonyK
Thank you for your help.

await core.executeAsModal(async () => {
  try {
      const activeLayer = app.activeDocument.activeLayers[0];
      const newLayer = await app.activeDocument.layers.add();
      const selection = await imaging.getSelection({});
      const img = await imaging.getPixels({
          layerID: activeLayer.id,
          sourceBounds: selection.sourceBounds,
          colorSpace: "RGB",
          targetSize: {
            height: selection.sourceBounds.bottom - selection.sourceBounds.top,
            width: selection.sourceBounds.right - selection.sourceBounds.left
          }
      });
      const bufferImg = await img.imageData.getData({chunky: true});
      const selectionWidth = selection.sourceBounds.right - selection.sourceBounds.left;
      const selectionHeight = selection.sourceBounds.bottom - selection.sourceBounds.top;
      const imgWidth = img.sourceBounds.right - img.sourceBounds.left;
      const imgHeight = img.sourceBounds.bottom - img.sourceBounds.top;
      const widthPer = imgWidth / selectionWidth * 100;
      const heightPer = imgHeight / selectionHeight * 100;
      const imageData = await imaging.createImageDataFromBuffer(bufferImg, {width:selectionWidth, height: selectionHeight, components: 4, colorSpace: "RGB"});
      await imaging.putPixels({
          layerID: newLayer.id,
          imageData: imageData,
          targetBounds: { "left": selection.sourceBounds.left, "top": selection.sourceBounds.top }
      });
      await newLayer.scale(widthPer, heightPer);
      await newLayer.translate(img.sourceBounds.left - newLayer.bounds.left, img.sourceBounds.top - newLayer.bounds.top)
  } catch (e) {
      console.log(e);
  }
});

Hi Taka,

You certainly can do this with the Imaging API. I would be remiss if I didn’t mention that just the steps above could also be done by:

  1. Select the target layer.
  2. Set the selection.
  3. Copy
  4. Paste
    → Repeat

Also, you can use app.activeDocument.selection.bounds instead of imaging.getSelection.

Lastly, the stretching you are seeing is due to using the targetSize option for getPixels. Without that option, you won’t see the scaling. You will have to account for the trimmed buffer as it will only contain the smallest rectangle that encompasses the non-empty pixels.

I will be updating the documentation to clarify that targetSize is for scaling.

Sam

Sam, Thank you for your reply.

I learned a lot from your reply.

I will keep working hard on the development of UXP.