Skip to main content
Peter Kahrel
Community Expert
Community Expert
January 28, 2010
Question

JS/PS CS3: identify single pixels sticking out

  • January 28, 2010
  • 3 replies
  • 6022 views

In a bitmap, is it possible to identify single pixels sticking out from a shape? Let's say I have this black shape in a black-and-white bitmap:

   xxxxxxxx

   xxxxxxxx

   xxxxxxxx

   xxxxxxxx

        x

an 8 by 4 rectangle with one pixel sticking out from the bottom. Question is, can I find such pixels using a script (JS) and make it white?

Thanks,

Peter

This topic has been closed for replies.

3 replies

Inspiring
January 29, 2010

This may sound like a stupid question, but will this always be black and white for the colors?

Also, from your example, if you look at the large vertical section there is one stray black pixel on the right side. There are also 2 stray white pixels in the upper left and lower right corners. Are you looking to take care of those also? I guess I'm just wondering exactly what would make a pixel stray or not stray.

Paul Riggott
Inspiring
January 28, 2010

Just a theory..

If it is a rectangle shape you might be able to :-

Select the area

Get the selection bounds

Make a work path set to 1 (One of the bounds should be one less than the selection bounds) also check that there is only 4 pathpoints.

Then compare each bound, then you could make a new selection and fill.

Peter Kahrel
Community Expert
Community Expert
January 28, 2010

Paul,

Thanks for the suggestion. But I'd prefer not to make a selection -- I've got hundreds of these things...

Peter

Paul Riggott
Inspiring
January 28, 2010

Ah now I see, another idea.

Select all the black ..

function selectBlack() {
    var desc63 = new ActionDescriptor();
    desc63.putInteger( charIDToTypeID('Fzns'), 13 );
        var desc64 = new ActionDescriptor();
        desc64.putDouble( charIDToTypeID('Lmnc'), 0.000000 );
        desc64.putDouble( charIDToTypeID('A   '), 0.000000 );
        desc64.putDouble( charIDToTypeID('B   '), 0.000000 );
    desc63.putObject( charIDToTypeID('Mnm '), charIDToTypeID('LbCl'), desc64 );
        var desc65 = new ActionDescriptor();
        desc65.putDouble( charIDToTypeID('Lmnc'), 0.000000 );
        desc65.putDouble( charIDToTypeID('A   '), 0.000000 );
        desc65.putDouble( charIDToTypeID('B   '), 0.000000 );
    desc63.putObject( charIDToTypeID('Mxm '), charIDToTypeID('LbCl'), desc65 );
    desc63.putInteger( stringIDToTypeID('colorModel'), 0 );
    executeAction( charIDToTypeID('ClrR'), desc63, DialogModes.NO );
};


Make a work path tolerance of 1, make selection from work path, invert and fill with white.

Inspiring
January 28, 2010

Peter, I don't know a method for working with a bitmap image. (there is NO histogram in bitmap mode) Would you be able to switch modes to grayscale and back? If so then this may work although Im NOT sure if I've overlooked something here. I only tested with a small file. I would not expect this kind of thing to be fast.

$.sleep(500); & WaitForRedraw(); can come out there just so I can see whats happening in the GUI.

#target photoshop

app.bringToFront();

function main() {

if (app.documents.length == 0) {

alert('You have NO document open?');

return;

}

var whiteRef = new SolidColor();

whiteRef.rgb.red = 255;

whiteRef.rgb.green = 255;

whiteRef.rgb.blue = 255;

var docRef = app.activeDocument;

with (docRef) {

// Horizontal selection

selection.select([[0, 0], [width , 0], [width, 1], [0, 1]]);

if (channels[0].histogram[0] == 1) {

alert('Single Pixel');

selection.fill(whiteRef);

}

for (var i = 0; i < height-1; i++) {

selection.translateBoundary(0, 1);

$.sleep(500);

WaitForRedraw();

if (channels[0].histogram[0] == 1) {

alert('Single Pixel');

selection.fill(whiteRef);

}

}

// Vertical selection

selection.select([[0, 0], [1 , 0], [1, height], [0, height]]);

if (channels[0].histogram[0] == 1) {

alert('Single Pixel');

selection.fill(whiteRef);

}

for (var i = 0; i < width-1; i++) {

selection.translateBoundary(1, 0);

$.sleep(500);

WaitForRedraw();

if (channels[0].histogram[0] == 1) {

alert('Single Pixel');

selection.fill(whiteRef);

}

}

selection.deselect();

}

};

main();

// Redraw the Screen

function WaitForRedraw() {

  var eventWait = charIDToTypeID('Wait');

  var enumRedrawComplete = charIDToTypeID('RdCm');

  var typeState = charIDToTypeID('Stte');

  var keyState = charIDToTypeID('Stte');

  var desc = new ActionDescriptor();

  desc.putEnumerated(keyState, typeState, enumRedrawComplete);

  executeAction(eventWait, desc, DialogModes.NO);

}

Peter Kahrel
Community Expert
Community Expert
January 28, 2010

Muppet,

Thanks for this. Temporarily converting to greyscale is not a problem. But unfortunately, your script breaks on this line:

selection.translateBoundary (0, 1);

with the error message "The document does not contain a selection". When I step through the script, I can see that it selects the first row of pixels, takes the first iteration in the for-loop fine, then in the second iteration the script breaks with the above-mentioned error message. So it looks as if the selection gets undone.

Scanning for lines with one pixel which are otherwise empty is not the right approach, though. I realise that my example may have led you to believe that it was, so let me give you a real example (see the screenshot). The line that the single pixel sits on has some other pixels set as well. So ideally, I would want to be able to look for a pixel that has one side adjacent to its own colour, the others to the opposite colour. In other words, if you're a black pixel and are surrounded by three white pixels and one black pixel, then you're single and you should change colour.

Sorry I didn't state this better earlier.

Thanks,

Peter