Hi!
I’m trying to generate a XMLHttpRequest to select a region of a RGB image (background layer, locked) to a Flask server that processes it and returns a mask back to the client.
The client then creates a new pixel layer (opacity: 50%, fill: 100%) and puts the returned mask over the selected region.
The input image is this:
and has the following characteristics:
W: 192 H: 263, Type: image/uncompressed
Colour space: RGB, profile: , has alpha: false
Pixel format: RGB
Components per pixel: 3, component size (bits): 8
Is chunky: false
The returned mask appears like this when saved to a file:
and it is sent back to the client side as a Base64 string appended to the data:image/png;base64,
tag in JSON format:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMAAAAEHAQAAAADQPXQSAAACD0lEQVR4nO3YMY4UMRCF4TcGCZA22JCQABFzBI6yEnfYdH0QAo7iayASH8GhA2MTdPdqZ1x/9xQiGm2H88n1XE89SetpmE8PgucGIBN8BRg0qhM0960qQSHI7oxEEL2jBkEnaHgrgkpQCDJBIojeWw0CPNHXTSZoO6Pem1Dd4YUg060SnYje8EHQRQvSiSa47tbIBIUAMzJBIojejEHQ8VYEjaAS4KhCkAkSQfSGD4JO0AgwoxIU96hMkAiiN2MQdIJGUAkwvBBkguTOiAAvF79uVCdoBJUAM4r7RCZIBBHgrJGrwjtBI8BRlaC4R/10n4gA541cM6oTNIJKgBmFILtHJYLoHTUIOkEjwIxKUNyjMkFyj4oAl408w2UjxxmXVT3DZSPHowpBJkgE0Rs+NbLB1MjhqKmRDaZGNijujEyQCKI3Y25khbmRFebFV5gXX6EQZALjOYBEEL2jjEYWMBpZwGjkIMOoaoFCkN0ZCIkgnv/WNrhs5M/pdK8gs5FK4U1BdlUKshvZ36MQZPeoRBC9o6yXRwr2y7M/yqxKAapSgEYUoBEFWHz3VhHAXnxvlN2IAiyuAIsrwOJ74dl9IrlP+OCtgr5Z8FFBnyx4kJ6W2j/8Hr/GGEmS3q0fM4ckPX7WF62f+dYUeEf/2x6v8Aq3Bb4vd5J0b8CdJD1Iy3/wxfNmnL7/kAH/8u311uAvGVaxWXY9M+cAAAAASUVORK5CYII=
The problem is that if I try to put the generated data as a RGB image in the pixel layer, it will be displayed in the “wrong” area.
For example, if I select the whole image in Photoshop, this is the final result (with the background layer invisible):
As you can see, the number 4 is not centered and it appears like this when the background layer visible:
If instead I put the data as a grayscale image, the generated layer is blank:
How can I create the new layer and put the received JSON data on it, so it overlaps the number 4 from the background layer?
Thanks!
The client code is as follows:
const photoshop = require("photoshop");
const app = photoshop.app;
const core = photoshop.core;
const imaging = photoshop.imaging;
async function execQuery()
{
const doc = app.activeDocument;
const docSize = { "height": doc.height, "width": doc.width };
let selection = null;
let selectionPixels = null;
let jpegData = "";
await core.executeAsModal(
async () =>
{
selection = await imaging.getSelection({});
if (selection.imageData === undefined)
{
throw "There is no selection.";
}
selectionPixels = await imaging.getPixels(
{
"sourceBounds": selection.sourceBounds,
"colorSpace": "RGB",
"targetSize": {
"height": selection.sourceBounds.bottom - selection.sourceBounds.top,
"width": selection.sourceBounds.right - selection.sourceBounds.left
}
}
);
let docPixels = await imaging.getPixels({
"documentID": doc.id,
"targetSize": docSize,
"componentSize": selectionPixels.imageData.componentSize,
"applyAlpha": selectionPixels.imageData.hasAlpha,
"colorProfile": "sRGB IEC61966-2.1"
});
jpegData = await imaging.encodeImageData({ "imageData": docPixels.imageData, "base64": true });
}
);
function connection(imageUrl, imageEncoded, options)
{
const url = "http://127.0.0.1:5000";
return new Promise((resolve, reject) =>
{
const req = new XMLHttpRequest();
req.onload = () =>
{
if (req.status === 200)
{
try
{
const json = JSON.parse(req.response);
addOverlay(json.masks, options);
}
catch (err)
{
reject(`Couldnt parse response. ${err.message}, ${req.response}`);
}
}
else
{
reject(`Request had an error: ${req.status}`);
}
};
// Generate request
req.onerror = reject;
req.onabort = reject;
req.open("POST", url);
req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
req.send(JSON.stringify({
"imageEncoded": imageEncoded,
"bounds": options.bounds
}));
});
}
const options = {
"bounds": selection.sourceBounds,
"components": selectionPixels.imageData.components,
"componentSize": selectionPixels.imageData.componentSize,
"height": selection.sourceBounds.bottom - selection.sourceBounds.top,
"width": selection.sourceBounds.right - selection.sourceBounds.left
};
await connection(doc.name, jpegData, options);
}
async function addOverlay(data, options)
{
await window.require('photoshop').core.executeAsModal(
async () =>
{
let buffer = null
switch (options.componentSize)
{
case 16:
buffer = Uint16Array.from(data);
break;
case 32:
buffer = Uint32Array.from(data);
break;
default:
buffer = Uint8Array.from(data);
break;
}
/* AS GRAYSCALE */
// let image = await imaging.createImageDataFromBuffer(buffer, {
// "width": options.width,
// "height": options.height,
// "components": 1,
// "chunky": false,
// "colorProfile": "Gray Gamma 2.2",
// "colorSpace": "Grayscale"
// });
/**/
/* AS RGB */
let image = await imaging.createImageDataFromBuffer(buffer, {
"width": options.width,
"height": options.height,
"components": options.components,
"chunky": false,
"colorProfile": "sRGB IEC61966-2.1",
"colorSpace": "RGB"
});
/**/
let doc = app.activeDocument;
let newLayer = await doc.createPixelLayer({
"name": "Overlay",
"opacity": 50
});
await imaging.putPixels({
"layerID": newLayer.id,
"imageData": image,
"replace": true,
"targetBounds": { "left": options.bounds.left, "top": options.bounds.top },
"commandName": "Add overlay layer"
});
image.dispose();
}
);
}