Skip to main content
Participant
July 21, 2013
Answered

draw line between black pixel : coordinates of selected pixels ?

  • July 21, 2013
  • 1 reply
  • 1650 views

Hi

I want to build a script which can check a Photoshop file and :

- find black pixel

- for each black pixel, look for another black pixel within maximum distance of 5 pixels

- then draw a line between the two black pixels.

I wrote this script below (my first script ...), but it's VERY slow (and my final image is VERY big), I think because I test the colour for each pixel of the image.

So another solution would be to first select black pixel with magic wand, then the script save all coordinates of selected pixels, then my script wil test only this pixels (less than 1% of the pixels are black in my image).

Is it possible with JavaScript ?

Thank you for your response !

Marc

function main(){

var startRulerUnits = app.preferences.rulerUnits;

app.preferences.rulerUnits = Units.PIXELS;

var myHeight = app.activeDocument.height;

var myWidth = app.activeDocument.width;

// Find black pixel

for(var i=5; i<myWidth; i++) {

  for(var j=5; j<myHeight; j++) {

   activeDocument.colorSamplers.removeAll()

   var sampler = activeDocument.colorSamplers.add([new UnitValue (i, 'px'), new UnitValue (j, 'px')]);

   if (sampler.color.rgb.hexValue === "000000") {

// For each black pixel, search another black pixel below left up to 5 pixels

    for (var m=i-5; m<i; m++) {

     for (var n=j+1; n<j+5; n++) {

      activeDocument.colorSamplers.removeAll()

      var test = activeDocument.colorSamplers.add([new UnitValue (m, 'px'), new UnitValue (n, 'px')]);

      if (test.color.rgb.hexValue === "000000") {

// Then draw a black line between the two black pixels

       var FillColour = new SolidColor;

       FillColour.rgb.hexValue = '000000';

       var ad=activeDocument;

       ad.selection.select([[m,n],[i,j],[m,n+1],[i,j+1]], SelectionType.REPLACE, 0, true);

       ad.selection.fill(FillColour);

       ad.selection.deselect()

      }

     }

// For each black pixel, search another black pixel below right up to 5 pixels

     for (var m=i+1; m<i+5; m++) {

      for (var n=j; n<j+5; n++) {

       activeDocument.colorSamplers.removeAll()

       var test = activeDocument.colorSamplers.add([new UnitValue (m, 'px'), new UnitValue (n, 'px')]);

       if (test.color.rgb.hexValue === "000000") {

// Then draw a black line between the two black pixels

        var FillColour = new SolidColor;

        FillColour.rgb.hexValue = '000000';

        var ad=activeDocument;

        ad.selection.select([[i,j],[m,n],[m,n+1],[i,j+1]], SelectionType.REPLACE, 0, true);

        ad.selection.fill(FillColour);

        ad.selection.deselect()

       }

      }

     }

    }

   }

  }

}

}

main();

This topic has been closed for replies.
Correct answer mdidish84

Sorry for the delay.

Thank you for your answer and all the details; unfortunately I can not get my goal with JS and Photoshop. I'll get another software (ImageJ ?).

If someone else has a suggestion, let me know.

Marc


If someone wants to do the same thing, the ImageJ software works very well on very large images (1 billion pixels) by the process according to> binary> close

1 reply

Inspiring
July 21, 2013

I think this task will be slow using javascript no matter how it is done.

You could use select color range to select the black pixels. But the selection bounds would include all the black pixels. You will not be able to tell where each black pixel is from the selection directly. You could convert the selection into a path. From the path you could get the x,y position of each subpath point to get the bounds of each pixel. I haven't tested this but you might only have to check the first pathpoint in each subpath to get the top left x,y position of the pixel. And there may be some top left to right bottom order in the subpaths that you could take advantage of.

Once you have the positions of each black point from the path the script should be able to determine if any are within 5px of each other just using those positions.

mdidish84Author
Participant
July 21, 2013

Michael L Hale a écrit:

From the path you could get the x,y position of each subpath point to get the bounds of each pixel.

Thank you for your proposition.

How can I get the x,y position of each subpath point ? When I try I obtain only the x,y position of each corner for the first subpath only ?

Marc

Inspiring
July 21, 2013

As I said, I didn't test this approach. I can't get Photoshop CC to convert single pixel selections into a path even when setting the tolerance to its minimum value. Are you sure your converted path has single pixel areas?

But to answer your question about how to get the positions of the path points -

function extractSubPathInfo(pathObj){

    var pathArray = new Array();

    var pl = pathObj.subPathItems.length;

    for(var s=0;s<pl;s++){

        var pArray = new Array();

          for(var i=0;i<pathObj.subPathItems.pathPoints.length;i++){

             pArray = new PathPointInfo;

             pArray.kind = pathObj.subPathItems.pathPoints.kind;

             pArray.anchor = pathObj.subPathItems.pathPoints.anchor;

             pArray.leftDirection = pathObj.subPathItems.pathPoints.leftDirection;

             pArray.rightDirection = pathObj.subPathItems.pathPoints.rightDirection;

          };

        pathArray[pathArray.length] = new Array();

        pathArray[pathArray.length - 1] = new SubPathInfo();

        pathArray[pathArray.length - 1].operation = pathObj.subPathItems.operation;

        pathArray[pathArray.length - 1].closed = pathObj.subPathItems.closed;

        pathArray[pathArray.length - 1].entireSubPath = pArray;

    };

    return pathArray;

};

var myPathInfo = extractSubPathInfo(app.activeDocument.pathItems.getByName('Path 1'));

var xyArray = [];

// get the first pathPoint.anchor from each subPath

for(spIndex=0;spIndex<myPathInfo.length;spIndex++){

    xyArray.push(myPathInfo[spIndex].entireSubPath[0].anchor);

}

alert('All the first anchors:\r'+xyArray);

alert('The first pathPoint from the first subPath:\r'+xyArray[0]);