Copy link to clipboard
Copied
Hi All
I have a CSV that has around 24,000 lines of X,Y coordinates (LED Tape pixels in real life)
What i was wondering is there a way to import this data to Photoshop and have it colour the said pixels with a 1 pixel pencil for example?
I hope this thought makes sence
Regards
Steve
Save the following in a `.psjs` file:
const photoshop = require("photoshop");
const app = photoshop.app;
const core = photoshop.core;
const executeAsModal = core.executeAsModal;
const imaging = photoshop.imaging;
const storage = require("uxp").storage;
const lfs = storage.localFileSystem;
const constants = photoshop.constants;
const convertStringToArray = (str) => {
return str.split("\n").map((line) => {
const [x, y] = line.split(";");
return { x: parseInt(x, 10), y: parseInt(y, 10)
...
Copy link to clipboard
Copied
In my estimate this would be so slow as to be a waste of time.
But quite frankly I may not understand what exactly you mean without seeing some more information.
Are there RGB vales or is this just on/off or …?
Please provide (a relevant part of) the file or at least meaningful screenshots.
Copy link to clipboard
Copied
Totally so in a Lighting Program we can create the lights and the pixels and export the X,Y coordinates.
What i need to do is to create a "UV Map" of this in a file so that the animators can create video for the pixel tape.
I just need eacg x,y pixel to be any colour - black - its so the animators know where the pixels are in a UV space
One screen shot here is of the Lighting Software - the other is a very very small sample of the X,Y coordinates
Copy link to clipboard
Copied
Also curious on what the pixel width and height of the canvas is.
Copy link to clipboard
Copied
10000px x 600px (but this may be broken down into different sections depending)
Copy link to clipboard
Copied
Although this is possible to script, I agree with @c.pfaffenbichler that it wouldn't be worth it as Photoshop is the wrong tool for the job.
Take a look at other tools, the most common appears to be a Python script:
https://www.geeksforgeeks.org/create-2d-pixel-plot-in-python/
Copy link to clipboard
Copied
I suppose there would be alternatives to using the Pencil Tool in Photoshop (Paths, …), but I think reading the csv-file itself would be pretty slow when performed from Photoshop.
Copy link to clipboard
Copied
I suppose there would be alternatives to using the Pencil Tool in Photoshop (Paths, …), but I think reading the csv-file itself would be pretty slow when performed from Photoshop.
By @c.pfaffenbichler
I think it would be compared to the dedicated libraries found in Python, however, I don't know how slow this would be in ExtendScript... 24K of X/Y coordinates to read and plot sounds slow.
I would read the CSV data using a function from:
// MOCK READ VARIABLES FROM CSV
pixGen(0, 0);
pixGen(1, 1);
function pixGen(theX, theY) {
// 1x1 PIXEL
var theR = theX + 1;
var theB = theY + 1;
var idmake = stringIDToTypeID( "make" );
var desc768 = new ActionDescriptor();
var idnull = stringIDToTypeID( "null" );
var ref306 = new ActionReference();
var idcontentLayer = stringIDToTypeID( "contentLayer" );
ref306.putClass( idcontentLayer );
desc768.putReference( idnull, ref306 );
var idusing = stringIDToTypeID( "using" );
var desc769 = new ActionDescriptor();
var idtype = stringIDToTypeID( "type" );
var desc770 = new ActionDescriptor();
var idcolor = stringIDToTypeID( "color" );
var desc771 = new ActionDescriptor();
var idgray = stringIDToTypeID( "gray" );
desc771.putDouble( idgray, 100.000000 );
var idgrayscale = stringIDToTypeID( "grayscale" );
desc770.putObject( idcolor, idgrayscale, desc771 );
var idsolidColorLayer = stringIDToTypeID( "solidColorLayer" );
desc769.putObject( idtype, idsolidColorLayer, desc770 );
var idshape = stringIDToTypeID( "shape" );
var desc772 = new ActionDescriptor();
var idunitValueQuadVersion = stringIDToTypeID( "unitValueQuadVersion" );
desc772.putInteger(idunitValueQuadVersion, 1);
/////
var idtop = stringIDToTypeID( "top" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc772.putUnitDouble(idtop, idpixelsUnit, theY);
var idleft = stringIDToTypeID( "left" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc772.putUnitDouble(idleft, idpixelsUnit, theX);
var idbottom = stringIDToTypeID( "bottom" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc772.putUnitDouble(idbottom, idpixelsUnit, theB);
var idright = stringIDToTypeID( "right" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc772.putUnitDouble(idright, idpixelsUnit, theR);
/////
var idtopRight = stringIDToTypeID( "topRight" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc772.putUnitDouble(idtopRight, idpixelsUnit, 0.000000);
var idtopLeft = stringIDToTypeID( "topLeft" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc772.putUnitDouble(idtopLeft, idpixelsUnit, 0.000000);
var idbottomLeft = stringIDToTypeID( "bottomLeft" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc772.putUnitDouble(idbottomLeft, idpixelsUnit, 0.000000);
var idbottomRight = stringIDToTypeID( "bottomRight" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc772.putUnitDouble(idbottomRight, idpixelsUnit, 0.000000);
/////
var idrectangle = stringIDToTypeID( "rectangle" );
desc769.putObject( idshape, idrectangle, desc772 );
var idstrokeStyle = stringIDToTypeID( "strokeStyle" );
var desc773 = new ActionDescriptor();
var idstrokeStyleVersion = stringIDToTypeID( "strokeStyleVersion" );
desc773.putInteger( idstrokeStyleVersion, 2 );
var idstrokeEnabled = stringIDToTypeID( "strokeEnabled" );
desc773.putBoolean( idstrokeEnabled, true );
var idfillEnabled = stringIDToTypeID( "fillEnabled" );
desc773.putBoolean( idfillEnabled, true );
var idstrokeStyleLineWidth = stringIDToTypeID( "strokeStyleLineWidth" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc773.putUnitDouble( idstrokeStyleLineWidth, idpixelsUnit, 0.000000 );
var idstrokeStyleLineDashOffset = stringIDToTypeID( "strokeStyleLineDashOffset" );
var idpointsUnit = stringIDToTypeID( "pointsUnit" );
desc773.putUnitDouble( idstrokeStyleLineDashOffset, idpointsUnit, 0.000000 );
var idstrokeStyleMiterLimit = stringIDToTypeID( "strokeStyleMiterLimit" );
desc773.putDouble( idstrokeStyleMiterLimit, 100.000000 );
var idstrokeStyleLineCapType = stringIDToTypeID( "strokeStyleLineCapType" );
var idstrokeStyleLineCapType = stringIDToTypeID( "strokeStyleLineCapType" );
var idstrokeStyleButtCap = stringIDToTypeID( "strokeStyleButtCap" );
desc773.putEnumerated( idstrokeStyleLineCapType, idstrokeStyleLineCapType, idstrokeStyleButtCap );
var idstrokeStyleLineJoinType = stringIDToTypeID( "strokeStyleLineJoinType" );
var idstrokeStyleLineJoinType = stringIDToTypeID( "strokeStyleLineJoinType" );
var idstrokeStyleMiterJoin = stringIDToTypeID( "strokeStyleMiterJoin" );
desc773.putEnumerated( idstrokeStyleLineJoinType, idstrokeStyleLineJoinType, idstrokeStyleMiterJoin );
var idstrokeStyleLineAlignment = stringIDToTypeID( "strokeStyleLineAlignment" );
var idstrokeStyleLineAlignment = stringIDToTypeID( "strokeStyleLineAlignment" );
var idstrokeStyleAlignCenter = stringIDToTypeID( "strokeStyleAlignCenter" );
desc773.putEnumerated( idstrokeStyleLineAlignment, idstrokeStyleLineAlignment, idstrokeStyleAlignCenter );
var idstrokeStyleScaleLock = stringIDToTypeID( "strokeStyleScaleLock" );
desc773.putBoolean( idstrokeStyleScaleLock, false );
var idstrokeStyleStrokeAdjust = stringIDToTypeID( "strokeStyleStrokeAdjust" );
desc773.putBoolean( idstrokeStyleStrokeAdjust, false );
var idstrokeStyleLineDashSet = stringIDToTypeID( "strokeStyleLineDashSet" );
var list163 = new ActionList();
desc773.putList( idstrokeStyleLineDashSet, list163 );
var idstrokeStyleBlendMode = stringIDToTypeID( "strokeStyleBlendMode" );
var idblendMode = stringIDToTypeID( "blendMode" );
var idnormal = stringIDToTypeID( "normal" );
desc773.putEnumerated( idstrokeStyleBlendMode, idblendMode, idnormal );
var idstrokeStyleOpacity = stringIDToTypeID( "strokeStyleOpacity" );
var idpercentUnit = stringIDToTypeID( "percentUnit" );
desc773.putUnitDouble( idstrokeStyleOpacity, idpercentUnit, 100.000000 );
var idstrokeStyleContent = stringIDToTypeID( "strokeStyleContent" );
var desc774 = new ActionDescriptor();
var idcolor = stringIDToTypeID( "color" );
var desc775 = new ActionDescriptor();
var idgray = stringIDToTypeID( "gray" );
desc775.putDouble( idgray, 100.000000 );
var idgrayscale = stringIDToTypeID( "grayscale" );
desc774.putObject( idcolor, idgrayscale, desc775 );
var idsolidColorLayer = stringIDToTypeID( "solidColorLayer" );
desc773.putObject( idstrokeStyleContent, idsolidColorLayer, desc774 );
var idstrokeStyleResolution = stringIDToTypeID( "strokeStyleResolution" );
desc773.putDouble( idstrokeStyleResolution, 72.000000 );
var idstrokeStyle = stringIDToTypeID( "strokeStyle" );
desc769.putObject( idstrokeStyle, idstrokeStyle, desc773 );
var idcontentLayer = stringIDToTypeID( "contentLayer" );
desc768.putObject( idusing, idcontentLayer, desc769 );
var idlayerID = stringIDToTypeID( "layerID" );
desc768.putInteger( idlayerID, 2 );
executeAction( idmake, desc768, DialogModes.NO );
}
Copy link to clipboard
Copied
One doesn't even need to read the CSV. It's easy enough to reformat the CSV data as function calls as demonstrated above... But pasting in 24K of lines wouldn't be ideal, but would provide a usable result.
l'll look at adding the CSV parsing code tomorrow.
Copy link to clipboard
Copied
I have only tested with a .CSV with 600 rows... I'm not sure what will happen when you throw 24,000 at it!
This script will create a new blank doc and read the X, Y comma-separated pixel values from the .csv file (assumed as upper left) and plot them in black.
Run time ~14-25 seconds for the 600 rows of data on a 2019 MacBook Pro 16GB RAM.
/*
Plot LED Co-ordinates From CSV.jsx
v1.0 18th January 2024, Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/csv-data-to-colour-pixels/m-p/14358713
*/
#target photoshop
// Select and validate the CSV file
var csvFile = File.openDialog("Select the CSV file:");
if (csvFile.exists) {
if (csvFile.length > 0) {
// Hide panels
app.togglePalettes();
// Create the new doc
function s2t(s) {
return app.stringIDToTypeID(s);
}
var descriptor = new ActionDescriptor();
var descriptor2 = new ActionDescriptor();
var list = new ActionList();
descriptor2.putString( s2t( "name" ), csvFile.name.replace(/\.[^\.]+$/, '') );
descriptor2.putBoolean( s2t( "artboard" ), false );
descriptor2.putBoolean( s2t( "autoPromoteBackgroundLayer" ), false );
descriptor2.putClass( s2t( "mode" ), s2t( "grayscaleMode" ));
descriptor2.putUnitDouble( s2t( "width" ), s2t( "distanceUnit" ), 10000.000000 );
descriptor2.putUnitDouble( s2t( "height" ), s2t( "distanceUnit" ), 600.000000 );
descriptor2.putUnitDouble( s2t( "resolution" ), s2t( "densityUnit" ), 72.000000 );
descriptor2.putDouble( s2t( "pixelScaleFactor" ), 1.000000 );
descriptor2.putEnumerated( s2t( "fill" ), s2t( "fill" ), s2t( "white" ));
descriptor2.putInteger( s2t( "depth" ), 8 );
descriptor2.putString( s2t( "profile" ), "Gray Gamma 2.2" );
descriptor2.putList( s2t( "guides" ), list );
descriptor.putObject( s2t( "new" ), s2t( "document" ), descriptor2 );
executeAction( s2t( "make" ), descriptor, DialogModes.NO );
// Setup the script timer
var timeDiff = {
setStartTime: function () {
d = new Date();
time = d.getTime();
},
getDiff: function () {
d = new Date();
t = d.getTime() - time;
time = d.getTime();
return t;
}
};
timeDiff.setStartTime();
// CSV open, read & close
csvFile.open("r");
var theData = csvFile.read();
csvFile.close();
// CSV to array
var theDataArray = parseCSV(theData);
// Loop over the CSV data
for (var i = 0; i < theDataArray.length; i++) {
var csvValueX = theDataArray[i].toString().split(',')[0];
var csvValueY = theDataArray[i].toString().split(',')[1];
csvValueXcleaned = parseInt(csvValueX);
csvValueYcleaned = parseInt(csvValueY);
// Debugger
$.writeln(csvValueXcleaned);
$.writeln(csvValueYcleaned);
// Plot the "pixel"
pixGen(csvValueXcleaned, csvValueYcleaned);
// Merge the pixel layer, we really don't want 24,000 layers!
executeAction( stringIDToTypeID( "mergeLayersNew" ), new ActionDescriptor(), DialogModes.NO );
}
// End of script
app.togglePalettes();
alert("Script completed!" + "\n" + "(" + timeDiff.getDiff() / 1000 + " seconds)");
} else {
app.beep();
alert('The CSV file is blank!');
}
}
///// FUNCTIONS /////
function parseCSV(theData, delimiter) {
/*
Courtesy of William Campbell
https://community.adobe.com/t5/photoshop-ecosystem-discussions/does-any\.$one-have-a-script-that-utilizes-a-csv-to-create-text-layers/m-p/13117458
*/
// theData: String = contents of a CSV csvFile
// delimiter: character that separates columns
// undefined defaults to comma
// Returns: Array [[String row, String column]]
var c = ""; // Character at index
var d = delimiter || ","; // Default to comma
var endIndex = theData.length;
var index = 0;
var maxIndex = endIndex - 1;
var q = false; // "Are we in quotes?"
var result = []; // Array of rows (array of column arrays)
var row = []; // Array of columns
var v = ""; // Column value
while (index < endIndex) {
c = theData[index];
if (q) { // In quotes
if (c == "\"") {
// Found quote; look ahead for another
if (index < maxIndex && theData[index + 1] == "\"") {
// Found another quote means escaped
// Increment and add to column value
index++;
v += c;
} else {
// Next character not a quote; last quote not escaped
q = !q; // Toggle "Are we in quotes?"
}
} else {
// Add character to column value
v += c;
}
} else { // Not in quotes
if (c == "\"") {
// Found quote
q = !q; // Toggle "Are we in quotes?"
} else if (c == "\n" || c == "\r") {
// Reached end of line
// Test for CRLF
if (c == "\r" && index < maxIndex) {
if (theData[index + 1] == "\n") {
// Skip trailing newline
index++;
}
}
// Column and row complete
row.push(v);
v = "";
// Add row to result if first row or length matches first row
if (result.length === 0 || row.length == result[0].length) {
result.push(row);
}
row = [];
} else if (c == d) {
// Found comma; column complete
row.push(v);
v = "";
} else {
// Add character to column value
v += c;
}
}
if (index == maxIndex) {
// Reached end of theData; flush
if (v.length || c == d) {
row.push(v);
}
// Add row to result if length matches first row
if (row.length == result[0].length) {
result.push(row);
}
break;
}
index++;
}
return result;
}
function pixGen(theX, theY) {
// 1x1 PIXEL
var theR = theX + 1;
var theB = theY + 1;
var idmake = stringIDToTypeID( "make" );
var desc768 = new ActionDescriptor();
var idnull = stringIDToTypeID( "null" );
var ref306 = new ActionReference();
var idcontentLayer = stringIDToTypeID( "contentLayer" );
ref306.putClass( idcontentLayer );
desc768.putReference( idnull, ref306 );
var idusing = stringIDToTypeID( "using" );
var desc769 = new ActionDescriptor();
var idtype = stringIDToTypeID( "type" );
var desc770 = new ActionDescriptor();
var idcolor = stringIDToTypeID( "color" );
var desc771 = new ActionDescriptor();
var idgray = stringIDToTypeID( "gray" );
desc771.putDouble( idgray, 100.000000 );
var idgrayscale = stringIDToTypeID( "grayscale" );
desc770.putObject( idcolor, idgrayscale, desc771 );
var idsolidColorLayer = stringIDToTypeID( "solidColorLayer" );
desc769.putObject( idtype, idsolidColorLayer, desc770 );
var idshape = stringIDToTypeID( "shape" );
var desc772 = new ActionDescriptor();
var idunitValueQuadVersion = stringIDToTypeID( "unitValueQuadVersion" );
desc772.putInteger(idunitValueQuadVersion, 1);
var idtop = stringIDToTypeID( "top" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc772.putUnitDouble(idtop, idpixelsUnit, theY);
var idleft = stringIDToTypeID( "left" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc772.putUnitDouble(idleft, idpixelsUnit, theX);
var idbottom = stringIDToTypeID( "bottom" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc772.putUnitDouble(idbottom, idpixelsUnit, theB);
var idright = stringIDToTypeID( "right" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc772.putUnitDouble(idright, idpixelsUnit, theR);
var idrectangle = stringIDToTypeID( "rectangle" );
desc769.putObject( idshape, idrectangle, desc772 );
var idstrokeStyle = stringIDToTypeID( "strokeStyle" );
var desc773 = new ActionDescriptor();
var idstrokeStyleVersion = stringIDToTypeID( "strokeStyleVersion" );
desc773.putInteger( idstrokeStyleVersion, 2 );
var idstrokeEnabled = stringIDToTypeID( "strokeEnabled" );
desc773.putBoolean( idstrokeEnabled, true );
var idfillEnabled = stringIDToTypeID( "fillEnabled" );
desc773.putBoolean( idfillEnabled, true );
var idstrokeStyleLineWidth = stringIDToTypeID( "strokeStyleLineWidth" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc773.putUnitDouble( idstrokeStyleLineWidth, idpixelsUnit, 0.000000 );
var idstrokeStyleLineDashOffset = stringIDToTypeID( "strokeStyleLineDashOffset" );
var idpointsUnit = stringIDToTypeID( "pointsUnit" );
desc773.putUnitDouble( idstrokeStyleLineDashOffset, idpointsUnit, 0.000000 );
var idstrokeStyleMiterLimit = stringIDToTypeID( "strokeStyleMiterLimit" );
desc773.putDouble( idstrokeStyleMiterLimit, 100.000000 );
var idstrokeStyleLineCapType = stringIDToTypeID( "strokeStyleLineCapType" );
var idstrokeStyleLineCapType = stringIDToTypeID( "strokeStyleLineCapType" );
var idstrokeStyleButtCap = stringIDToTypeID( "strokeStyleButtCap" );
desc773.putEnumerated( idstrokeStyleLineCapType, idstrokeStyleLineCapType, idstrokeStyleButtCap );
var idstrokeStyleLineJoinType = stringIDToTypeID( "strokeStyleLineJoinType" );
var idstrokeStyleLineJoinType = stringIDToTypeID( "strokeStyleLineJoinType" );
var idstrokeStyleMiterJoin = stringIDToTypeID( "strokeStyleMiterJoin" );
desc773.putEnumerated( idstrokeStyleLineJoinType, idstrokeStyleLineJoinType, idstrokeStyleMiterJoin );
var idstrokeStyleLineAlignment = stringIDToTypeID( "strokeStyleLineAlignment" );
var idstrokeStyleLineAlignment = stringIDToTypeID( "strokeStyleLineAlignment" );
var idstrokeStyleAlignCenter = stringIDToTypeID( "strokeStyleAlignCenter" );
desc773.putEnumerated( idstrokeStyleLineAlignment, idstrokeStyleLineAlignment, idstrokeStyleAlignCenter );
var idstrokeStyleScaleLock = stringIDToTypeID( "strokeStyleScaleLock" );
desc773.putBoolean( idstrokeStyleScaleLock, false );
var idstrokeStyleStrokeAdjust = stringIDToTypeID( "strokeStyleStrokeAdjust" );
desc773.putBoolean( idstrokeStyleStrokeAdjust, false );
var idstrokeStyleLineDashSet = stringIDToTypeID( "strokeStyleLineDashSet" );
var list163 = new ActionList();
desc773.putList( idstrokeStyleLineDashSet, list163 );
var idstrokeStyleBlendMode = stringIDToTypeID( "strokeStyleBlendMode" );
var idblendMode = stringIDToTypeID( "blendMode" );
var idnormal = stringIDToTypeID( "normal" );
desc773.putEnumerated( idstrokeStyleBlendMode, idblendMode, idnormal );
var idstrokeStyleOpacity = stringIDToTypeID( "strokeStyleOpacity" );
var idpercentUnit = stringIDToTypeID( "percentUnit" );
desc773.putUnitDouble( idstrokeStyleOpacity, idpercentUnit, 100.000000 );
var idstrokeStyleContent = stringIDToTypeID( "strokeStyleContent" );
var desc774 = new ActionDescriptor();
var idcolor = stringIDToTypeID( "color" );
var desc775 = new ActionDescriptor();
var idgray = stringIDToTypeID( "gray" );
desc775.putDouble( idgray, 100.000000 );
var idgrayscale = stringIDToTypeID( "grayscale" );
desc774.putObject( idcolor, idgrayscale, desc775 );
var idsolidColorLayer = stringIDToTypeID( "solidColorLayer" );
desc773.putObject( idstrokeStyleContent, idsolidColorLayer, desc774 );
var idstrokeStyleResolution = stringIDToTypeID( "strokeStyleResolution" );
desc773.putDouble( idstrokeStyleResolution, 72.000000 );
var idstrokeStyle = stringIDToTypeID( "strokeStyle" );
desc769.putObject( idstrokeStyle, idstrokeStyle, desc773 );
var idcontentLayer = stringIDToTypeID( "contentLayer" );
desc768.putObject( idusing, idcontentLayer, desc769 );
executeAction( idmake, desc768, DialogModes.NO );
}
https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html
Copy link to clipboard
Copied
I understand that you want to fill a blank image (say, 200x120px) with data coming from a CSV.
It's doable, the process must be split in two parts:
Hope this helps!
Davide
Copy link to clipboard
Copied
I'd look at ImageJ to see if there is a script or built-in support. That app is designed for specialty image processing.
Copy link to clipboard
Copied
I'd look at ImageJ to see if there is a script or built-in support. That app is designed for specialty image processing.
By @Lumigraphics
I thought of that too, but all I found was Python or MatLab.
Copy link to clipboard
Copied
Save the following in a `.psjs` file:
const photoshop = require("photoshop");
const app = photoshop.app;
const core = photoshop.core;
const executeAsModal = core.executeAsModal;
const imaging = photoshop.imaging;
const storage = require("uxp").storage;
const lfs = storage.localFileSystem;
const constants = photoshop.constants;
const convertStringToArray = (str) => {
return str.split("\n").map((line) => {
const [x, y] = line.split(";");
return { x: parseInt(x, 10), y: parseInt(y, 10) };
});
};
const width = 20;
const height = 20;
const { types, formats, modes, errors } = require("uxp").storage;
let f = await lfs.getFileForOpening();
const txtContent = await f.read({ format: formats.utf8 });
const points = convertStringToArray(txtContent);
const doc = await app.documents.add({
width,
height,
mode: constants.NewDocumentMode.GRAYSCALE,
});
let pixelsArray = new Uint8Array(width * height).fill(255);
points.forEach(({ x, y }) => {
pixelsArray[y * width + x] = 0;
});
const imageData = await imaging.createImageDataFromBuffer(pixelsArray, {
width,
height,
components: 1,
colorSpace: "Grayscale",
});
await imaging.putPixels({
layerID: app.activeDocument.activeLayers[0].id,
imageData,
commandName: "LED stuff",
});
Then File > Scripts > Browse... and get it.
It will pop up a file selection dialog; I've pointed it to a `pixels.csv` file with the following content:
0;0
1;1
2;2
3;3
4;4
5;5
6;6
7;7
8;8
9;9
10;10
11;11
12;12
13;13
14;14
15;15
16;16
17;17
18;18
19;19
It creates a new document, 20x20px (the doc size is hardwired for simplicity) and fill it with black pixels at the x,y coords in the csv, like so:
It's a toy example, but you can tweak it to fit your purposes—if I've properly understood what you're after. Please note that in PS the cartesian plane points downwards, y values must be adjusted if one expects it to be as we're taught in school 🙂
Cheers,
Davide
Copy link to clipboard
Copied
Thanks for sharing. Although there are most likely optimisations and improvements to be made in my script, at 14-25 seconds for 600 rows of data it is slow as expected in ExtendScript. Perhaps XML or JSON would read faster to read than CSV, but I'm not the one to answer that question! Perhaps it's the 1x1px vector layer that is slow.
Further tests:
CSV read of 600 rows of X/Y data = ~0.2 seconds
Create 600 1x1px raster layers = ~8 seconds
So the bulk of the processing time is in plotting and merging the 600 layers at ~14-25 seconds
Your UXP script ran in less than ~1 second for the same 600 rows!
Copy link to clipboard
Copied
I have been bugging Adobe with feature requests for a pixel setter since Adobe Generator came out (2014, maybe?) The Imaging API is a blessing—the one, truly new feature that sets UXP and ExtendScript apart, IMHO. I've had some legit fun in my book doing all sorts of things with it 😁
If you combine the Imaging API with Hybrid plugins or WASM, you can get better performances for elaborate image processing routines, but even with JS alone, it's rather impressive as is.